mobile-debug-mcp 0.32.4 → 0.34.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/plugins/marketplace.json +20 -0
- package/.claude-plugin/marketplace.json +14 -0
- package/.cursor-plugin/marketplace.json +16 -0
- package/.github/copilot-instructions.md +7 -0
- package/.github/workflows/ci.yml +21 -0
- package/AGENTS.md +21 -10
- package/README.md +69 -4
- package/agent-plugin/.claude-plugin/plugin.json +20 -0
- package/agent-plugin/.codex-plugin/plugin.json +34 -0
- package/agent-plugin/.cursor-plugin/plugin.json +23 -0
- package/agent-plugin/.mcp.json +14 -0
- package/agent-plugin/README.md +9 -3
- package/agent-plugin/assets/mobile-debug-tools.svg +28 -0
- package/agent-plugin/mcp.json +1 -1
- package/agent-plugin/plugin.json +1 -1
- package/agent-plugin/skills/mobile-debug-mcp/SKILL.md +113 -1
- package/dist/debugger/android.js +78 -0
- package/dist/debugger/guard.js +30 -0
- package/dist/debugger/sessions.js +262 -0
- package/dist/debugger/worker.js +165 -0
- package/dist/interact/android.js +10 -4
- package/dist/interact/conditional-action.js +68 -0
- package/dist/interact/index.js +70 -14
- package/dist/interact/ios.js +14 -8
- package/dist/manage/android.js +4 -3
- package/dist/manage/ios.js +3 -2
- package/dist/observe/android.js +25 -4
- package/dist/observe/evidence.js +280 -0
- package/dist/observe/index.js +33 -6
- package/dist/observe/ios.js +25 -6
- package/dist/observe/readiness-service.js +124 -0
- package/dist/observe/readiness.js +88 -0
- package/dist/observe/recording.js +165 -0
- package/dist/observe/snapshot-metadata.js +10 -2
- package/dist/observe/system-trace-android.js +135 -0
- package/dist/observe/system-trace.js +285 -0
- package/dist/server/common.js +9 -0
- package/dist/server/condition-schema.js +32 -0
- package/dist/server/debugger-handlers.js +38 -0
- package/dist/server/debugger-schema.js +42 -0
- package/dist/server/journey-schema.js +4 -2
- package/dist/server/readiness-schema.js +12 -0
- package/dist/server/system-trace-schema.js +17 -0
- package/dist/server/tool-definitions.js +51 -0
- package/dist/server/tool-handlers.js +294 -105
- package/dist/server-core.js +3 -3
- package/dist/server.js +34 -0
- package/dist/system/index.js +5 -4
- package/dist/utils/exec.js +2 -0
- package/dist/utils/ios/utils.js +4 -4
- package/dist/utils/java.js +14 -12
- package/dist/utils/operation-budget.js +26 -2
- package/dist/utils/resolve-device.js +9 -0
- package/docs/CHANGELOG.md +15 -0
- package/docs/specs/020-conditional-actions/intent.md +62 -0
- package/docs/specs/020-conditional-actions/plan.md +214 -0
- package/docs/specs/020-conditional-actions/spec.md +301 -0
- package/docs/specs/021-app-readiness-signals/intent.md +40 -0
- package/docs/specs/021-app-readiness-signals/plan.md +102 -0
- package/docs/specs/021-app-readiness-signals/spec.md +144 -0
- package/docs/specs/022-correlated-evidence/device-evidence.json +60 -0
- package/docs/specs/022-correlated-evidence/intent.md +37 -0
- package/docs/specs/022-correlated-evidence/modul8-evidence.json +1062 -0
- package/docs/specs/022-correlated-evidence/modul8-selector-fix-evidence.json +336 -0
- package/docs/specs/022-correlated-evidence/plan.md +171 -0
- package/docs/specs/022-correlated-evidence/spec.md +123 -0
- package/docs/specs/023-android-system-traces/device-evidence.json +38 -0
- package/docs/specs/023-android-system-traces/emulator-recheck.json +38 -0
- package/docs/specs/023-android-system-traces/intent.md +40 -0
- package/docs/specs/023-android-system-traces/plan.md +117 -0
- package/docs/specs/023-android-system-traces/spec.md +120 -0
- package/docs/specs/024-android-heap-dump-capture/intent.md +39 -0
- package/docs/specs/025-android-runtime-debugger/intent.md +40 -0
- package/docs/specs/025-android-runtime-debugger/plan.md +104 -0
- package/docs/specs/025-android-runtime-debugger/spec.md +182 -0
- package/docs/specs/process.md +213 -0
- package/docs/tools/TOOLS.md +5 -0
- package/docs/tools/debugger.md +104 -0
- package/docs/tools/evidence.md +82 -0
- package/docs/tools/interact.md +125 -2
- package/docs/tools/observe.md +70 -0
- package/docs/tools/system-traces.md +126 -0
- package/package.json +1 -1
- package/scripts/agent-plugin.mjs +68 -8
- package/src/debugger/android.ts +65 -0
- package/src/debugger/guard.ts +26 -0
- package/src/debugger/sessions.ts +168 -0
- package/src/debugger/worker.ts +122 -0
- package/src/interact/android.ts +10 -4
- package/src/interact/conditional-action.ts +75 -0
- package/src/interact/index.ts +57 -28
- package/src/interact/ios.ts +14 -8
- package/src/manage/android.ts +4 -3
- package/src/manage/ios.ts +3 -2
- package/src/observe/android.ts +33 -6
- package/src/observe/evidence.ts +262 -0
- package/src/observe/index.ts +32 -8
- package/src/observe/ios.ts +32 -8
- package/src/observe/readiness-service.ts +94 -0
- package/src/observe/readiness.ts +84 -0
- package/src/observe/snapshot-metadata.ts +12 -1
- package/src/observe/system-trace-android.ts +133 -0
- package/src/observe/system-trace.ts +218 -0
- package/src/server/common.ts +7 -0
- package/src/server/condition-schema.ts +32 -0
- package/src/server/debugger-handlers.ts +29 -0
- package/src/server/debugger-schema.ts +37 -0
- package/src/server/journey-schema.ts +4 -2
- package/src/server/readiness-schema.ts +12 -0
- package/src/server/system-trace-schema.ts +17 -0
- package/src/server/tool-definitions.ts +49 -0
- package/src/server/tool-handlers.ts +182 -21
- package/src/server-core.ts +3 -3
- package/src/server.ts +24 -0
- package/src/system/index.ts +7 -5
- package/src/types.ts +30 -1
- package/src/utils/exec.ts +2 -0
- package/src/utils/ios/utils.ts +4 -4
- package/src/utils/java.ts +13 -12
- package/src/utils/operation-budget.ts +24 -2
- package/src/utils/resolve-device.ts +10 -0
- package/test/device/automated/debugger/runtime.android.test.ts +203 -0
- package/test/device/automated/observe/correlated-evidence.smoke.ts +70 -0
- package/test/device/automated/observe/system-trace.smoke.ts +104 -0
- package/test/device/manual/interact/conditional_actions.manual.ts +95 -0
- package/test/device/manual/interact/modul8_selector_tap.manual.ts +63 -0
- package/test/device/manual/interact/readiness.manual.ts +99 -0
- package/test/fixtures/debugger-app/MainActivity.java +46 -0
- package/test/fixtures/debugger-app/NoLocals.java +7 -0
- package/test/fixtures/debugger-app/README.md +13 -0
- package/test/fixtures/debugger-app/build.ts +29 -0
- package/test/fixtures/readiness-app/MainActivity.java +23 -0
- package/test/fixtures/readiness-app/README.md +12 -0
- package/test/fixtures/readiness-app/build.ts +37 -0
- package/test/fixtures/readiness-app/main.m +27 -0
- package/test/helpers/perfetto.ts +59 -0
- package/test/unit/debugger/guards.test.ts +46 -0
- package/test/unit/debugger/native.test.ts +33 -0
- package/test/unit/debugger/sessions.test.ts +83 -0
- package/test/unit/observe/android_tree_acquisition.test.ts +2 -0
- package/test/unit/observe/capture_debug_snapshot.test.ts +42 -32
- package/test/unit/observe/compact_tree_error.test.ts +24 -0
- package/test/unit/observe/conditional_snapshots.test.ts +33 -0
- package/test/unit/observe/correlated-evidence.test.ts +128 -0
- package/test/unit/observe/ios_tree_acquisition.test.ts +2 -0
- package/test/unit/observe/readiness.test.ts +41 -0
- package/test/unit/observe/readiness_native.test.ts +68 -0
- package/test/unit/observe/system-trace-android.test.ts +52 -0
- package/test/unit/observe/system-trace.test.ts +166 -0
- package/test/unit/server/conditional_actions.test.ts +299 -0
- package/test/unit/server/conditional_schema.test.ts +59 -0
- package/test/unit/server/correlated-evidence.test.ts +194 -0
- package/test/unit/server/readiness.test.ts +170 -0
- package/test/unit/server/selector_tap_target.test.ts +79 -0
- package/test/unit/server/system-trace.test.ts +64 -0
- package/test/unit/server/tap_selector.test.ts +2 -0
- package/worker/DebuggerWorker.java +160 -0
- package/skills/mobile-debug-tools-usage/SKILL.md +0 -96
- /package/{skills → .agents/skills}/README.md +0 -0
- /package/{skills → .agents/skills}/mcp-builder/SKILL.md +0 -0
- /package/{skills → .agents/skills}/mcp-builder/references/build-flags.md +0 -0
- /package/{skills → .agents/skills}/mcp-builder/references/diagnostics-schema.md +0 -0
- /package/{skills → .agents/skills}/mcp-builder/references/toolchain-details.md +0 -0
- /package/{skills → .agents/skills}/spec-review/SKILL.md +0 -0
- /package/{skills → .agents/skills}/spec-review/references/spec-review-checklist.md +0 -0
- /package/{skills → .agents/skills}/spec-review/references/spec-review-template.md +0 -0
- /package/{skills → .agents/skills}/test-authoring/SKILL.md +0 -0
- /package/{skills → .agents/skills}/test-authoring/references/repo-test-layout.md +0 -0
- /package/{skills → .agents/skills}/test-authoring/references/test-authoring-workflow.md +0 -0
- /package/{skills → .agents/skills}/test-authoring/references/test-quality-checklist.md +0 -0
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
# Specification: Android runtime debugger
|
|
2
|
+
|
|
3
|
+
Date: 2026-10-30. Status: approved.
|
|
4
|
+
Intent: [approved intent](intent.md), approved by the user's “yes” in this conversation.
|
|
5
|
+
Source: [issue #68](https://github.com/clivejefferies/mobile-debug-tools/issues/68).
|
|
6
|
+
|
|
7
|
+
## Behaviour and supported environment
|
|
8
|
+
|
|
9
|
+
Provide managed Java/Kotlin bytecode debugging of running, debuggable Android
|
|
10
|
+
apps using an independently developed Java JDI worker over ADB-forwarded JDWP.
|
|
11
|
+
No Debroid implementation or artifacts are reused. Require host JDK 17+ with
|
|
12
|
+
`jdk.jdi` and `javac`, Android platform-tools, an authorized Android device, and
|
|
13
|
+
a JDWP-visible app process. Package worker sources with the npm distribution;
|
|
14
|
+
compile into a private, version-keyed host cache on first use. Missing tooling
|
|
15
|
+
must not prevent ordinary MCP tools or server startup.
|
|
16
|
+
|
|
17
|
+
Initial verification target: API 36 arm64 emulator; other Android versions and
|
|
18
|
+
physical devices require separate evidence. iOS, native frames, expression
|
|
19
|
+
evaluation, method invocation, mutation, coroutine reconstruction, heap capture,
|
|
20
|
+
launch-under-debugger, and changing app debuggability are excluded. Kotlin
|
|
21
|
+
inspection follows emitted JVM/DEX debug metadata; do not promise source-level
|
|
22
|
+
coroutine or inline-function reconstruction.
|
|
23
|
+
|
|
24
|
+
## MCP contracts
|
|
25
|
+
|
|
26
|
+
All new inputs reject unknown fields. Strings are nonempty and bounded to 512
|
|
27
|
+
characters unless otherwise stated; IDs are opaque server-issued strings.
|
|
28
|
+
Every tool accepts `timeoutMs` (integer 100–30000, default 10000); event waits
|
|
29
|
+
default to 1000. Tables list other inputs; `?` means optional.
|
|
30
|
+
|
|
31
|
+
| Tool | Inputs | Result payload |
|
|
32
|
+
| --- | --- | --- |
|
|
33
|
+
| `get_debugger_capabilities` | `platform: android`, `deviceId`, `appId`, `processId?` | Prerequisites, candidate processes, supported operations and limitations; no attach |
|
|
34
|
+
| `attach_debugger` | `platform: android`, `deviceId`, `appId`, `processId?` | Session and resolved target |
|
|
35
|
+
| `get_debugger_state` | `debugSessionId` | Current state, stop summary, breakpoint statuses, cleanup |
|
|
36
|
+
| `set_debugger_breakpoint` | `debugSessionId`, `className`, `line` | Breakpoint ID, requested/resolved locations, `pending`/`verified`/`rejected` |
|
|
37
|
+
| `remove_debugger_breakpoint` | `debugSessionId`, `breakpointId` | Removal outcome; repeated removal of an owned ID succeeds |
|
|
38
|
+
| `wait_for_debugger_event` | `debugSessionId`, `afterSequence?` | Ordered events, next cursor and explicit overflow indication |
|
|
39
|
+
| `get_debugger_stack` | `debugSessionId`, `stopId`, `threadId`, `offset?`, `limit?` | Frames, opaque frame IDs and pagination |
|
|
40
|
+
| `get_debugger_locals` | `debugSessionId`, `stopId`, `frameId` | Bounded shallow local values and availability |
|
|
41
|
+
| `step_debugger` | `debugSessionId`, `stopId`, `threadId`, `kind: into/over/out` | Acknowledged transition to running; await a later event separately |
|
|
42
|
+
| `resume_debugger` | `debugSessionId`, `stopId` | Acknowledged resume |
|
|
43
|
+
| `detach_debugger` | `debugSessionId` | Terminal state and cleanup; idempotent and usable for cleanup retry |
|
|
44
|
+
|
|
45
|
+
`processId` and `line` are positive safe integers. Omitted process ID is allowed
|
|
46
|
+
only when exactly one matching app process is JDWP-visible. Resolve package UID,
|
|
47
|
+
process name, PID and process-start identity before and after attach; reject
|
|
48
|
+
ambiguity, mismatch or PID reuse. Never select the first connected device.
|
|
49
|
+
|
|
50
|
+
Responses use existing MCP text JSON serialization:
|
|
51
|
+
`{success, debug_session_id, device, target, state, captured_at_ms, capabilities,
|
|
52
|
+
limitations, cleanup, ...payload}`; pre-session fields may be null. Target includes
|
|
53
|
+
app ID, PID, process name and process-start identity. Failures add
|
|
54
|
+
`error: {code, message, retryable}`. Codes cover `INVALID_ARGUMENT`,
|
|
55
|
+
`DEBUGGER_UNSUPPORTED`, `DEVICE_UNAVAILABLE`, `PROCESS_NOT_FOUND`,
|
|
56
|
+
`PROCESS_AMBIGUOUS`, `PROCESS_CHANGED`, `DEBUGGER_BUSY`, `DEBUGGER_ATTACH_FAILED`,
|
|
57
|
+
`DEBUGGER_NOT_FOUND`, `DEBUGGER_NOT_PAUSED`, `DEBUGGER_STALE_REFERENCE`,
|
|
58
|
+
`DEBUGGER_LOCATION_UNAVAILABLE`, `DEBUGGER_DISCONNECTED`, `DEBUGGER_TIMEOUT`,
|
|
59
|
+
`DEBUGGER_CANCELLED`, `DEBUGGER_WORKER_FAILED`, and `DEBUGGER_CLEANUP_FAILED`.
|
|
60
|
+
No automatic retry of attach, step or resume. Do not claim command delivery
|
|
61
|
+
establishes a later stop or UI outcome.
|
|
62
|
+
|
|
63
|
+
## Stops, inspection and events
|
|
64
|
+
|
|
65
|
+
States: `attaching`, `running`, `paused`, `detaching`, `detached`, `disconnected`,
|
|
66
|
+
`failed`. Serialize state-changing commands per session; event polling must not
|
|
67
|
+
block resume/detach. One active session per device, at most four per server.
|
|
68
|
+
Reject an existing debugger attachment without replacing it.
|
|
69
|
+
|
|
70
|
+
Breakpoints use exact binary class names and 1-based lines, without arbitrary
|
|
71
|
+
source paths. Bind all matching executable locations in loaded class loaders;
|
|
72
|
+
report class-loader identity and resolved source/line. Unloaded classes remain
|
|
73
|
+
pending via class-prepare requests. Missing executable lines/debug metadata are
|
|
74
|
+
explicitly unavailable; never silently move the breakpoint. Limit 100 breakpoints.
|
|
75
|
+
|
|
76
|
+
Breakpoint and step events suspend all app threads. Retain owned EventSets and
|
|
77
|
+
resume through their matching ownership; do not decrement unrelated suspension
|
|
78
|
+
counts. Non-stop events are promptly released. Each new stop has a unique
|
|
79
|
+
`stopId`, triggering thread ID, reason, locations and matching breakpoint IDs.
|
|
80
|
+
Simultaneous events share a stop summary. Step uses one-shot line stepping on
|
|
81
|
+
the chosen suspended thread; a competing breakpoint also completes that step
|
|
82
|
+
attempt and removes its request. A step acknowledgement does not wait for a stop.
|
|
83
|
+
|
|
84
|
+
Thread/frame IDs are stop-scoped. Resume, step, disconnect and detach invalidate
|
|
85
|
+
all inspection references before further commands can use them. Stack pagination
|
|
86
|
+
defaults to 20, maximum 100 per call and 1000 frames per stop. Locals return at
|
|
87
|
+
most 100 entries: primitives, null, strings truncated to 256 characters, and
|
|
88
|
+
object type/opaque identity summaries, without field traversal or `toString()`.
|
|
89
|
+
Expose truncation and missing debug metadata; unavailable locals are distinct
|
|
90
|
+
from a proven empty scope. Investigation found ART may return an empty variable
|
|
91
|
+
table without distinguishing absent metadata from no variables; report availability
|
|
92
|
+
as unknown with `EMPTY_OR_UNAVAILABLE_VARIABLE_METADATA`, rather than inferring an
|
|
93
|
+
empty scope. No retained object pinning.
|
|
94
|
+
|
|
95
|
+
Maintain a 256-event ring per session with increasing sequence, host receipt time,
|
|
96
|
+
kind and optional stop summary. Default cursor is zero; return at most 100 events
|
|
97
|
+
and a continuation cursor. Cursor overrun is explicit. Reject future cursors;
|
|
98
|
+
an empty wait returns success with `timed_out: true`, without changing the session.
|
|
99
|
+
|
|
100
|
+
## UI coordination and resource safety
|
|
101
|
+
|
|
102
|
+
While a session is paused, conservatively block action dispatch, lifecycle/data
|
|
103
|
+
management, and UI waits/assertions on that device with `DEBUGGER_PAUSED` before
|
|
104
|
+
native work. Journeys stop with completed steps preserved and no automatic retry.
|
|
105
|
+
Check at dispatch and within polling; a pause racing an already dispatched action
|
|
106
|
+
must preserve delivery evidence and mark verification blocked. Do not queue inputs
|
|
107
|
+
for resume. Use a device dispatch gate to serialize pause transitions with input
|
|
108
|
+
submission; inputs already submitted cannot be retracted.
|
|
109
|
+
|
|
110
|
+
Readiness tools return evidence-backed `debugger_paused` with debug session/target
|
|
111
|
+
identity and host timestamp without acquiring a UI tree. This is device-scoped
|
|
112
|
+
blocking evidence, not proof the paused app is foreground. Screenshots, raw trees
|
|
113
|
+
and logs remain available within their existing bounds and carry the known pause
|
|
114
|
+
annotation; their success does not establish readiness. Other devices and iOS
|
|
115
|
+
retain existing behaviour. Unknown/disconnected debugger state cannot imply pause.
|
|
116
|
+
|
|
117
|
+
Detach automatically after 60 seconds continuously paused, five minutes without
|
|
118
|
+
client activity, or 30 minutes total session lifetime; polling cannot extend the
|
|
119
|
+
pause/total limit. Emit the expiry reason. Timeouts/cancellation of inspection
|
|
120
|
+
leave a known session intact; uncertain state-changing commands trigger teardown
|
|
121
|
+
and invalidate references. Cancelling an event wait only cancels that wait.
|
|
122
|
+
|
|
123
|
+
Cleanup has its own ten-second deadline: remove owned requests, release owned
|
|
124
|
+
suspensions/dispose the JDI connection, stop the owned worker, and remove only
|
|
125
|
+
the session's exact ADB forward. Never kill/restart the app, ADB server or another
|
|
126
|
+
debugger. On worker failure, disconnect its transport and verify obtainable
|
|
127
|
+
cleanup facts; never claim the app resumed without evidence. Report cleanup as
|
|
128
|
+
`pending`/`complete`/`failed`, remaining resources and execution state as unknown
|
|
129
|
+
when necessary. Block new sessions on that device until owned cleanup completes.
|
|
130
|
+
The worker watches parent-pipe EOF; server shutdown also requests cleanup. Abrupt
|
|
131
|
+
host/device loss may prevent confirmed cleanup and must be documented explicitly.
|
|
132
|
+
|
|
133
|
+
Use argv-based subprocesses and a dedicated worker with bounded JSON-lines IPC
|
|
134
|
+
(1 MiB/message), request IDs and stderr-only diagnostics. JDI runs through an
|
|
135
|
+
owned loopback forward, never a public listener. Whitelist commands; do not log
|
|
136
|
+
locals or protocol values. Locals may contain sensitive data and are returned
|
|
137
|
+
only on request; no persistent inspection dump or upload. Retain up to 100 terminal
|
|
138
|
+
session summaries for ten minutes, clearing locals, frames and events at teardown.
|
|
139
|
+
|
|
140
|
+
## Acceptance and verification
|
|
141
|
+
|
|
142
|
+
1. A dedicated debuggable Java fixture attaches on the selected device/process;
|
|
143
|
+
ambiguous, non-debuggable, replaced and already-debugged targets fail safely.
|
|
144
|
+
2. Pending/loaded breakpoints stop at the expected line; stack and known local
|
|
145
|
+
values are correct; each step mode and resume produce observed execution.
|
|
146
|
+
3. Old stop/frame/thread references fail after resume; missing metadata and
|
|
147
|
+
truncation are explicit.
|
|
148
|
+
4. UI action/wait/readiness tools recognise pauses, including mid-journey stops;
|
|
149
|
+
another device is unaffected and resumed UI changes are independently verified.
|
|
150
|
+
5. Explicit detach, expiry, cancellation, disconnect and worker failure invalidate
|
|
151
|
+
references and clean up owned resources without altering unrelated forwards.
|
|
152
|
+
|
|
153
|
+
Use focused self-running unit tests plus a new isolated fixture with debug line
|
|
154
|
+
and local-variable tables. Run `npm run verify`, `npm run test:device`, and focused
|
|
155
|
+
end-to-end calls through the updated server. Record exact build/device and each
|
|
156
|
+
journey as pass/fail/blocked/unrun. Current CI uses Node 18; manual Android CI uses
|
|
157
|
+
JDK 17/API 30. Existing smoke tests do not prove debugger behaviour; add worker
|
|
158
|
+
compilation/packaging checks and explicit debugger coverage.
|
|
159
|
+
|
|
160
|
+
Affected areas: new debugger/worker modules, tool definitions/handlers, readiness,
|
|
161
|
+
interaction dispatch/polling, lifecycle guards, shutdown, native-tool status,
|
|
162
|
+
packaging, fixtures/tests and tool/README/changelog documentation. Correct existing
|
|
163
|
+
JDWP capability reporting: ADB/device presence alone is not debugger readiness.
|
|
164
|
+
|
|
165
|
+
## Investigation and approval
|
|
166
|
+
|
|
167
|
+
Checkout 0.33.0 contains no debugger implementation. Host Java 23 and ADB 37.0.1
|
|
168
|
+
are available; outside sandbox, `emulator-5554` is online (API 36 arm64). Existing
|
|
169
|
+
latency fixture lacks `android:debuggable`; a dedicated fixture is required.
|
|
170
|
+
No debugger session was attached and no debugging journey is verified yet.
|
|
171
|
+
|
|
172
|
+
Primary references: [JDI VM lifecycle](https://docs.oracle.com/en/java/javase/17/docs/api/jdk.jdi/com/sun/jdi/VirtualMachine.html),
|
|
173
|
+
[EventSet suspension ownership](https://docs.oracle.com/en/java/javase/21/docs/api/jdk.jdi/com/sun/jdi/event/EventSet.html),
|
|
174
|
+
[frame lifetime](https://docs.oracle.com/en/java/javase/17/docs/api/jdk.jdi/com/sun/jdi/StackFrame.html),
|
|
175
|
+
[step requests](https://docs.oracle.com/en/java/javase/17/docs/api/jdk.jdi/com/sun/jdi/request/StepRequest.html),
|
|
176
|
+
and [ADB](https://developer.android.com/tools/adb). ART/JDI interoperability must
|
|
177
|
+
be established by fixture evidence; API documentation alone does not prove it.
|
|
178
|
+
|
|
179
|
+
The user approved this complete specification with “yes” on 2026-10-30 in this
|
|
180
|
+
conversation, including all-thread
|
|
181
|
+
suspension, conservative device-wide UI blocking, shallow locals, JDK dependency,
|
|
182
|
+
and automatic detach limits. Implementation is authorized within this scope.
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
# Development process
|
|
2
|
+
|
|
3
|
+
This is the required development workflow for all agents contributing to
|
|
4
|
+
`mobile-debug-mcp`. Read it before planning, editing, or reviewing changes,
|
|
5
|
+
including work delegated to another agent. [AGENTS.md](../../AGENTS.md) is the
|
|
6
|
+
shared entrypoint; tool-specific instructions must point here rather than
|
|
7
|
+
maintain a competing workflow. Explicit user instructions take precedence.
|
|
8
|
+
|
|
9
|
+
The agent owns investigation, implementation, and verification. The user or
|
|
10
|
+
explicitly designated maintainer owns product decisions and approval. Existing
|
|
11
|
+
explicit approval in the current conversation counts for unchanged scope; do
|
|
12
|
+
not ask for it again. Never invent approval or treat silence as approval.
|
|
13
|
+
|
|
14
|
+
## Choose the path
|
|
15
|
+
|
|
16
|
+
Use the full process for new MCP capabilities, material tool behaviour or
|
|
17
|
+
contract changes, and significant architecture changes. Use the lightweight
|
|
18
|
+
path for fixes restoring agreed behaviour, refactors that preserve contracts,
|
|
19
|
+
small maintenance changes, and documentation-only work. Move to the full path
|
|
20
|
+
if investigation exposes new behaviour or unresolved product decisions.
|
|
21
|
+
|
|
22
|
+
For the lightweight path:
|
|
23
|
+
|
|
24
|
+
1. State the intended outcome and scope in the conversation.
|
|
25
|
+
2. Inspect the relevant code, contracts, tests, and instructions.
|
|
26
|
+
3. Make focused changes and run applicable verification below.
|
|
27
|
+
4. Report the changes, evidence, and remaining limitations.
|
|
28
|
+
|
|
29
|
+
Separate intent, spec, and plan files and approval stages are not required for
|
|
30
|
+
the lightweight path. Documentation-only changes require a diff, link/path,
|
|
31
|
+
and consistency check; application builds and device tests are unnecessary.
|
|
32
|
+
|
|
33
|
+
For the full path, keep `intent.md`, `spec.md`, and `plan.md` together under
|
|
34
|
+
`docs/specs/<next-number>-<feature>/`, following existing directory naming.
|
|
35
|
+
Reuse the relevant feature directory where appropriate. Do not rewrite old
|
|
36
|
+
specs retrospectively; add only what is needed for the current scope.
|
|
37
|
+
|
|
38
|
+
## Keep artifacts concise
|
|
39
|
+
|
|
40
|
+
Use these writing defaults for the full path:
|
|
41
|
+
|
|
42
|
+
- `intent.md`: about 200 words covering the problem, outcome, scope, and open
|
|
43
|
+
questions, with the required source and status information.
|
|
44
|
+
- `spec.md`: about 800 words focused on behaviour, contracts, failure handling,
|
|
45
|
+
acceptance criteria, and decisions needing approval.
|
|
46
|
+
- `plan.md`: a short implementation checklist and verification table. Append
|
|
47
|
+
actual results as work finishes.
|
|
48
|
+
|
|
49
|
+
These are defaults, not limits. Add detail when complexity or risk requires it;
|
|
50
|
+
retain all applicable stage requirements and approval gates below. Record each
|
|
51
|
+
decision once and reference it from later documents instead of repeating it.
|
|
52
|
+
Use examples only where a contract would otherwise be ambiguous. Link detailed
|
|
53
|
+
logs and evidence rather than copying them, while keeping enough result detail
|
|
54
|
+
in the plan to assess coverage and any remaining failures or blockers.
|
|
55
|
+
|
|
56
|
+
## 1. Capture intent
|
|
57
|
+
|
|
58
|
+
Write `intent.md` with:
|
|
59
|
+
|
|
60
|
+
- The original problem and its source, preserving the originator's meaning.
|
|
61
|
+
- Desired outcome, affected MCP clients, platforms, and observable success criteria.
|
|
62
|
+
- Constraints, exclusions, assumptions, and open questions.
|
|
63
|
+
- Originator, date, and status; do not invent identities.
|
|
64
|
+
|
|
65
|
+
Show the captured intent and obtain explicit agreement before drafting the
|
|
66
|
+
spec. A clarification about one detail does not approve the complete intent.
|
|
67
|
+
Record the approving response and its scope. While approval is pending,
|
|
68
|
+
continue only investigation or independent work that does not assume it.
|
|
69
|
+
|
|
70
|
+
**Exit:** the user has accepted the problem and scope, and questions blocking
|
|
71
|
+
specification are answered.
|
|
72
|
+
|
|
73
|
+
## 2. Investigate and specify
|
|
74
|
+
|
|
75
|
+
Inspect the current checkout and preserve unrelated changes. Ground the design
|
|
76
|
+
in existing code, tests, and [tool contracts](../tools/TOOLS.md). Reuse helpers
|
|
77
|
+
and conventions rather than introducing new frameworks without a concrete need.
|
|
78
|
+
|
|
79
|
+
Load applicable repository skills from [.agents/skills/](../../.agents/skills/README.md):
|
|
80
|
+
|
|
81
|
+
- [Test authoring](../../.agents/skills/test-authoring/SKILL.md) before creating or updating tests.
|
|
82
|
+
- [MCP builder](../../.agents/skills/mcp-builder/SKILL.md) for build, installation, or native toolchain work.
|
|
83
|
+
- [Spec review](../../.agents/skills/spec-review/SKILL.md) when reviewing an RFC or spec draft.
|
|
84
|
+
|
|
85
|
+
For device-dependent behaviour, inspect the current tool flow on an available
|
|
86
|
+
device or emulator when practical. Record the platform, device, server build,
|
|
87
|
+
observed behaviour, and inaccessible states. If unavailable, record the concrete
|
|
88
|
+
blocker and available code/test evidence; plan a runnable device check.
|
|
89
|
+
|
|
90
|
+
Write `spec.md` defining:
|
|
91
|
+
|
|
92
|
+
- Required behaviour and plain-language acceptance criteria linked to the intent.
|
|
93
|
+
- Scope, exclusions, failure, recovery, cancellation, and timeout behaviour.
|
|
94
|
+
- MCP tool names, input schemas, response/error shapes, and compatibility impact.
|
|
95
|
+
- Android/iOS differences and unsupported environments where applicable.
|
|
96
|
+
- Device/process targeting, resource ownership and cleanup, concurrency, and
|
|
97
|
+
subprocess handling where relevant.
|
|
98
|
+
- Security and privacy implications, including arguments, logs, screenshots,
|
|
99
|
+
UI trees, credentials, and potentially destructive device actions.
|
|
100
|
+
- Affected modules, risks, assumptions, and unresolved decisions.
|
|
101
|
+
- Approval status and a reference to the actual approving decision.
|
|
102
|
+
|
|
103
|
+
Show the complete spec and obtain explicit acceptance before planning
|
|
104
|
+
implementation. An instruction to implement an already accepted spec authorises
|
|
105
|
+
that scope.
|
|
106
|
+
|
|
107
|
+
**Exit:** the spec is accepted and decisions blocking correctness or scope are resolved.
|
|
108
|
+
|
|
109
|
+
## 3. Plan implementation and verification
|
|
110
|
+
|
|
111
|
+
Save `plan.md` with:
|
|
112
|
+
|
|
113
|
+
- References to intent, spec, and approval decisions.
|
|
114
|
+
- Affected files/modules and an ordered implementation checklist.
|
|
115
|
+
- Dependencies, risks, compatibility, rollout, and cleanup steps as applicable.
|
|
116
|
+
- Each acceptance criterion mapped to a meaningful automated or device check.
|
|
117
|
+
- Exact verification commands and required runtime/toolchain versions.
|
|
118
|
+
- For device checks: platform/device, starting state, actions, expected result,
|
|
119
|
+
evidence to capture, fixture requirements, and cleanup.
|
|
120
|
+
- Unavailable prerequisites, their owner where known, and how to obtain them or
|
|
121
|
+
perform an equivalent check.
|
|
122
|
+
|
|
123
|
+
Use the existing lightweight self-running `tsx` test pattern. No separate
|
|
124
|
+
scenario language, scenario-approval stage, or new test framework is required.
|
|
125
|
+
Routine technical planning choices do not need separate approval.
|
|
126
|
+
|
|
127
|
+
Check scarce prerequisites early. Treat missing access as a planning blocker
|
|
128
|
+
only when an essential acceptance criterion has no credible verification route.
|
|
129
|
+
Do not describe readiness checks as verification of unimplemented behaviour.
|
|
130
|
+
|
|
131
|
+
**Exit:** implementation is authorised within the accepted spec, the plan has
|
|
132
|
+
no unresolved blocking dependency, and essential criteria have credible checks.
|
|
133
|
+
|
|
134
|
+
## 4. Implement and handle discoveries
|
|
135
|
+
|
|
136
|
+
Implement the agreed scope, add meaningful regression coverage where needed,
|
|
137
|
+
and update the plan as work completes. Place tests according to the test-authoring
|
|
138
|
+
skill: automated unit tests in `test/unit/`, automated device checks in
|
|
139
|
+
`test/device/automated/`, and manual/debug helpers in `test/device/manual/`.
|
|
140
|
+
|
|
141
|
+
Review changed code, tests, and relevant callers for contract consistency,
|
|
142
|
+
platform differences, error handling, subprocess safety, resource cleanup,
|
|
143
|
+
state ownership, and reliable assertions. Review depth should match the risk.
|
|
144
|
+
|
|
145
|
+
When new evidence changes the work:
|
|
146
|
+
|
|
147
|
+
- Update the plan for routine implementation choices.
|
|
148
|
+
- Update the spec for design or contract changes. Obtain agreement before
|
|
149
|
+
implementing material changes to behaviour, scope, permissions, data handling,
|
|
150
|
+
compatibility, or acceptance criteria.
|
|
151
|
+
- Update intent only if the problem or intended outcome changes; preserve the
|
|
152
|
+
original statement and record the accepted revision.
|
|
153
|
+
- Record blockers and continue independent work. Do not silently weaken requirements.
|
|
154
|
+
|
|
155
|
+
Keep [tool documentation](../tools/TOOLS.md), [README](../../README.md), and
|
|
156
|
+
[changelog](../CHANGELOG.md) aligned when usage or behaviour changes.
|
|
157
|
+
|
|
158
|
+
**Exit:** agreed implementation and relevant documentation are ready for verification.
|
|
159
|
+
|
|
160
|
+
## 5. Verify and report
|
|
161
|
+
|
|
162
|
+
For code or test changes, run focused checks during iteration and complete the
|
|
163
|
+
maintainer verification command from the repository root:
|
|
164
|
+
|
|
165
|
+
```sh
|
|
166
|
+
npm run verify
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
This currently runs lint, TypeScript build, all automated unit tests, and the
|
|
170
|
+
agent-plugin consistency check. Confirm scripts in [package.json](../../package.json)
|
|
171
|
+
and applicable [CI workflows](../../.github/workflows) in the current checkout;
|
|
172
|
+
report any difference between local validation and CI coverage.
|
|
173
|
+
|
|
174
|
+
For changes affecting native device interaction, platform tooling, or runtime
|
|
175
|
+
behaviour, also run applicable automated device checks:
|
|
176
|
+
|
|
177
|
+
```sh
|
|
178
|
+
npm run test:device
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
Confirm which platforms and behaviours the suite actually covers. Supplement
|
|
182
|
+
it with focused end-to-end tool calls on the updated server where required by
|
|
183
|
+
the acceptance criteria. A passing Android check does not establish iOS support;
|
|
184
|
+
a dispatched action or mocked subprocess does not prove a real device outcome.
|
|
185
|
+
|
|
186
|
+
For each relevant device journey, record the platform/device and server build,
|
|
187
|
+
starting state, actions/tool calls, expected and observed result, evidence, and
|
|
188
|
+
**pass**, **fail**, **blocked**, or **unrun** status. Include failure, recovery,
|
|
189
|
+
interruption, and cleanup paths where relevant. Restore device settings and
|
|
190
|
+
remove temporary test data after verification. If a platform or prerequisite is
|
|
191
|
+
unavailable, state the concrete blocker and next step rather than claiming full
|
|
192
|
+
verification.
|
|
193
|
+
|
|
194
|
+
For schema changes, check registration, dispatch, runtime validation, response
|
|
195
|
+
serialization, documentation, and callers/fixtures together. Distinguish local
|
|
196
|
+
compatibility checks from testing an installed or published package.
|
|
197
|
+
|
|
198
|
+
Investigate failures against the agreed contract. Do not weaken assertions,
|
|
199
|
+
skip tests, add suppressions, or lower validation rules merely to get a pass.
|
|
200
|
+
Distinguish pre-existing failures from regressions with evidence; neither is a
|
|
201
|
+
pass. Fix issues introduced by the change and report unrelated findings separately.
|
|
202
|
+
|
|
203
|
+
For documentation-only work, inspect the diff, validate changed relative links
|
|
204
|
+
and referenced paths/commands, and check consistency across agent entrypoints.
|
|
205
|
+
Required pull-request CI checks still apply.
|
|
206
|
+
|
|
207
|
+
**Exit:** all agreed work and applicable checks have passed. Otherwise, report
|
|
208
|
+
partial completion and identify failed, blocked, or unrun checks explicitly.
|
|
209
|
+
|
|
210
|
+
The final report states what changed, verification commands and outcomes,
|
|
211
|
+
relevant device evidence, focused review findings, and remaining limitations.
|
|
212
|
+
Summarise successful output rather than pasting full logs. Commit, push, publish,
|
|
213
|
+
and release only within the user's authorised workflow.
|
package/docs/tools/TOOLS.md
CHANGED
|
@@ -7,6 +7,11 @@ This repository groups the MCP tools into four areas aligned with the codebase:
|
|
|
7
7
|
- [interact](interact.md) — UI resolution, actions, waits, and deterministic verification
|
|
8
8
|
- [system](system.md) — environment and health checks
|
|
9
9
|
|
|
10
|
+
Correlation metadata and explicit action references are documented in
|
|
11
|
+
[correlated evidence](evidence.md). Android performance capture is documented in
|
|
12
|
+
[system traces](system-traces.md). Android bytecode debugging is documented in
|
|
13
|
+
[runtime debugger](debugger.md).
|
|
14
|
+
|
|
10
15
|
## Agent guidance
|
|
11
16
|
|
|
12
17
|
For interactive flows, the intended deterministic pattern is:
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
# Android runtime debugger
|
|
2
|
+
|
|
3
|
+
Optional managed Java/Kotlin bytecode debugging through an independently developed
|
|
4
|
+
JDI worker. Requires JDK 17+ (`java`, `javac`, `jdk.jdi`), Android platform-tools,
|
|
5
|
+
an authorized device and an already-running JDWP-visible debuggable app.
|
|
6
|
+
Android Studio JBR/standard JDK discovery follows existing Java helpers; `ADB_PATH`
|
|
7
|
+
is supported. The worker is compiled on demand into a private source/JDK-keyed
|
|
8
|
+
host temporary cache. Ordinary tools do not require Java or start a debugger.
|
|
9
|
+
Cache directories named `mobile-debug-jdi-*` can be removed when the server exits.
|
|
10
|
+
|
|
11
|
+
## Tools and flow
|
|
12
|
+
|
|
13
|
+
1. `get_debugger_capabilities` with `platform: "android"`, explicit `deviceId`,
|
|
14
|
+
`appId`, and optional positive `processId` probes prerequisites/candidate processes.
|
|
15
|
+
General `get_system_status` does not establish target-specific debugger readiness.
|
|
16
|
+
2. `attach_debugger` with the same target returns `debug_session_id`. If multiple
|
|
17
|
+
matching debuggable processes exist, provide `processId`. Package UID, process
|
|
18
|
+
name, PID and process-start identity are checked. Other debuggers are not replaced.
|
|
19
|
+
3. `set_debugger_breakpoint` takes `debugSessionId`, exact binary `className` and
|
|
20
|
+
1-based executable `line`. It returns `result.breakpoint_id`, status and resolved
|
|
21
|
+
source locations/class-loader IDs. Unloaded classes remain `pending`; missing
|
|
22
|
+
line metadata is rejected explicitly. No automatic source search/line relocation.
|
|
23
|
+
4. Trigger execution, then `wait_for_debugger_event` with `debugSessionId` and
|
|
24
|
+
`afterSequence` (initially zero). Retain `next_cursor`. Stop events contain
|
|
25
|
+
`stop_id`, `thread_id` and source locations. A step acknowledgement is not a stop.
|
|
26
|
+
5. `get_debugger_stack` takes `debugSessionId`, `stopId`, `threadId`, optional
|
|
27
|
+
`offset` and `limit` (20 default, 100 maximum; 1000-frame cap).
|
|
28
|
+
`get_debugger_locals` takes `debugSessionId`, `stopId`, `frameId`. It returns
|
|
29
|
+
`result.availability`, up to 100 shallow locals, and truncation information.
|
|
30
|
+
Primitive values are textual; strings truncate at 256 characters; objects have
|
|
31
|
+
type/identity summaries. Missing variable metadata is explicit. ART can return an empty table without
|
|
32
|
+
distinguishing absent metadata from a genuinely empty scope; these responses
|
|
33
|
+
use `availability: "unknown"`, `reason: "EMPTY_OR_UNAVAILABLE_VARIABLE_METADATA"`.
|
|
34
|
+
6. `step_debugger` takes `debugSessionId`, current `stopId`, `threadId` and
|
|
35
|
+
`kind: "into" | "over" | "out"`. It resumes and requests one line step.
|
|
36
|
+
`resume_debugger` takes `debugSessionId`, `stopId`. Both expire all old stop,
|
|
37
|
+
thread and frame references. Await the next stop using the event cursor.
|
|
38
|
+
7. `remove_debugger_breakpoint` takes `debugSessionId`, `breakpointId` and is
|
|
39
|
+
idempotent for an owned ID. `get_debugger_state` reads stop, breakpoint, terminal
|
|
40
|
+
reason and cleanup status. `detach_debugger` disposes the session and supports
|
|
41
|
+
repeated calls/retrying incomplete cleanup.
|
|
42
|
+
|
|
43
|
+
Every tool accepts integer `timeoutMs`, 100–30000 (default 10000; event waits
|
|
44
|
+
1000). Unknown arguments are rejected. Other strings are limited to 512 characters.
|
|
45
|
+
All session tools use camelCase input IDs; response fields use snake_case.
|
|
46
|
+
Successful operation payloads are under `result` where applicable; common fields
|
|
47
|
+
include `success`, `debug_session_id`, `device`, `target`, `state`,
|
|
48
|
+
`captured_at_ms`, `capabilities`, `limitations`, `cleanup`, `reason`, and `stop`.
|
|
49
|
+
Failures carry `error: {code, message, retryable}`. Event polls use top-level
|
|
50
|
+
`events`, `next_cursor`, `overflow`, `timed_out`; empty waits are successful.
|
|
51
|
+
The 256-event ring returns at most 100 entries; overflow must not be ignored.
|
|
52
|
+
|
|
53
|
+
## Suspension, limits and cleanup
|
|
54
|
+
|
|
55
|
+
Stops suspend all app threads. UI actions, app lifecycle/data changes, waits and
|
|
56
|
+
assertions on that device return `DEBUGGER_PAUSED`; inputs are not queued. A pause
|
|
57
|
+
racing input submission preserves delivery uncertainty and blocks verification.
|
|
58
|
+
Journeys preserve completed steps. Other devices are unaffected.
|
|
59
|
+
|
|
60
|
+
`get_app_readiness` returns evidence-backed `debugger_paused` without reading the
|
|
61
|
+
UI; readiness waits fail with `DEBUGGER_PAUSED`. This signal covers managed Android
|
|
62
|
+
sessions only and does not establish foreground app identity. Raw trees, screenshots
|
|
63
|
+
and logs remain available within their own timeouts; snapshot/log acquisition may
|
|
64
|
+
still fail while the app is suspended. Known pauses are annotated on observations.
|
|
65
|
+
|
|
66
|
+
The worker and host enforce automatic detach after 60 seconds continuously paused,
|
|
67
|
+
five minutes without client commands or 30 minutes total. Polling cannot extend
|
|
68
|
+
the pause or total limit. One active session per device, four per server; at most
|
|
69
|
+
100 distinct breakpoint IDs per session. Terminal summaries expire after ten
|
|
70
|
+
minutes and are capped at 100; inspection values and event history are cleared.
|
|
71
|
+
|
|
72
|
+
Detach releases debugger-owned suspension and removes only owned requests,
|
|
73
|
+
worker and the exact ADB forward. Cleanup is bounded separately to ten seconds;
|
|
74
|
+
retry `detach_debugger` if `cleanup.status` is `failed`. Never kill an app or ADB
|
|
75
|
+
server to clean up. Unexpected worker/transport loss reports execution state as
|
|
76
|
+
unknown; no resumption claim is inferred. Hard host/device loss can prevent
|
|
77
|
+
confirmed cleanup. Server shutdown and worker parent-pipe EOF request cleanup.
|
|
78
|
+
|
|
79
|
+
MCP request cancellation is supported. Cancelling an event wait leaves the
|
|
80
|
+
session intact. Inspection cancellation/timeouts preserve a known session;
|
|
81
|
+
uncertain mutation/attach outcomes trigger teardown. Do not automatically retry
|
|
82
|
+
step, resume or attach.
|
|
83
|
+
|
|
84
|
+
## Limits, privacy and evidence
|
|
85
|
+
|
|
86
|
+
There is no expression evaluation, object traversal, method invocation, mutation,
|
|
87
|
+
coroutine reconstruction, native debugger, iOS debugger or heap capture. Kotlin
|
|
88
|
+
results follow emitted bytecode/debug metadata; optimized/obfuscated apps may lack
|
|
89
|
+
useful source lines or locals. Locals may contain private data: values are returned
|
|
90
|
+
only on request, without protocol/value logging, persistent dumps or upload.
|
|
91
|
+
Worker heap is capped at 128 MiB; IPC and messages are bounded; forwarding remains loopback-only.
|
|
92
|
+
|
|
93
|
+
Verified environments and remaining checks are recorded in
|
|
94
|
+
[the implementation plan](../specs/025-android-runtime-debugger/plan.md).
|
|
95
|
+
To run the isolated fixture journey (installs then removes its own test package):
|
|
96
|
+
|
|
97
|
+
```sh
|
|
98
|
+
MCP_DEBUGGER_DEVICE=emulator-5554 npx tsx test/device/automated/debugger/runtime.android.test.ts
|
|
99
|
+
# Also exercise the real 60-second pause expiry:
|
|
100
|
+
MCP_DEBUGGER_DEVICE=emulator-5554 MCP_DEBUGGER_EXTENDED=1 npx tsx test/device/automated/debugger/runtime.android.test.ts
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
The ordinary device suite explicitly reports this journey unrun unless the device
|
|
104
|
+
is selected. Fixture compilation requires SDK platform/build-tools 36 and `javac -g`.
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
# Correlated evidence
|
|
2
|
+
|
|
3
|
+
Covered actions (`start_app`, `restart_app`, `tap`, `tap_element`, `swipe`,
|
|
4
|
+
`scroll_to_element`, `type_text`, `press_back`, `adjust_control`) return an
|
|
5
|
+
additive `evidence` object in their first JSON content block. Journey steps have
|
|
6
|
+
individual action IDs and share the journey correlation ID.
|
|
7
|
+
|
|
8
|
+
To associate a later observation, copy the action's `evidence.session_id` and
|
|
9
|
+
`evidence.action_id` into `actionRef`:
|
|
10
|
+
|
|
11
|
+
```json
|
|
12
|
+
{
|
|
13
|
+
"platform": "android",
|
|
14
|
+
"deviceId": "emulator-5554",
|
|
15
|
+
"actionRef": { "sessionId": "<evidence.session_id>", "actionId": "<evidence.action_id>" }
|
|
16
|
+
}
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
Supported observation tools: `capture_screenshot`, `get_ui_tree`,
|
|
20
|
+
`get_screen_fingerprint`, `capture_debug_snapshot`, `get_logs`, `read_log_stream`.
|
|
21
|
+
The reference object accepts only those two keys, each a string of 1–128
|
|
22
|
+
characters. Malformed references fail before collection. References never select
|
|
23
|
+
or redirect devices. A missing reference creates independent evidence; there is
|
|
24
|
+
no automatic association with the latest action.
|
|
25
|
+
|
|
26
|
+
Completed actions remain referenceable for 10 minutes, with at most 1,000 records
|
|
27
|
+
per server process. Restart changes the session. Unknown, expired, foreign-session,
|
|
28
|
+
or different-device references still collect independently: `association` is
|
|
29
|
+
`unavailable`, `association_reason` explains why, and `action_id` is null.
|
|
30
|
+
|
|
31
|
+
## Reading metadata
|
|
32
|
+
|
|
33
|
+
`session_id`, `correlation_id`, `action_id`, `device`, and `association` identify
|
|
34
|
+
the operation. Association is `self`, `explicit`, `internal`, `none`, or
|
|
35
|
+
`unavailable`. Target scope is the resolved device; UI evidence is device-wide.
|
|
36
|
+
`requested_action_ref` preserves an explicit reference, including unavailable ones.
|
|
37
|
+
|
|
38
|
+
Phase fields are server UTC epoch milliseconds:
|
|
39
|
+
|
|
40
|
+
- `operation_started_at_ms` / `operation_completed_at_ms`: this call.
|
|
41
|
+
- `dispatch_started_at_ms` / `dispatch_completed_at_ms`: actual action dispatch,
|
|
42
|
+
first start through last completion for multi-input actions.
|
|
43
|
+
- `verification_completed_at_ms`: verification attempt completion, including
|
|
44
|
+
failure or timeout; null when skipped. Read the existing verification status
|
|
45
|
+
to determine its outcome.
|
|
46
|
+
|
|
47
|
+
Unreached/uninstrumented phases are null. Host monotonic time governs ordering
|
|
48
|
+
and retention. A detected clock reversal yields unknown freshness and null age.
|
|
49
|
+
|
|
50
|
+
`observations` contains separate screenshot, UI-tree, fingerprint, activity, and
|
|
51
|
+
log records. Each has `evidence_id`, device, component status (`captured`, `failed`,
|
|
52
|
+
`omitted`), acquisition start/completion, source capture time, age, freshness and
|
|
53
|
+
reasons. Tree records retain snapshot session/revision references. Failed records
|
|
54
|
+
preserve available errors; disabled captures are omitted. Snapshot components
|
|
55
|
+
are collected independently, including fallback log reads; they are not atomic.
|
|
56
|
+
|
|
57
|
+
Visual freshness is evaluated when the response is assembled:
|
|
58
|
+
|
|
59
|
+
| Status | Meaning |
|
|
60
|
+
| --- | --- |
|
|
61
|
+
| `fresh` | Newly acquired with no known intervening covered dispatch; app state may still change. |
|
|
62
|
+
| `stale` | Before the associated action or superseded by a later covered dispatch. |
|
|
63
|
+
| `unknown` | Overlap, reuse, failure, unknown scope/timing, or clock discontinuity. |
|
|
64
|
+
| `not_applicable` | Omitted logs. |
|
|
65
|
+
|
|
66
|
+
Cached source times are preserved. `age_ms` is nullable; clients choose their own
|
|
67
|
+
age limits. Freshness does not replace conditional-action safeguards.
|
|
68
|
+
|
|
69
|
+
Log timestamps remain on their original device/unknown clock. Log records expose
|
|
70
|
+
`clock: "device_or_unknown"`, `event_time_comparable: false`, and nullable earliest/
|
|
71
|
+
latest parseable entry times. Collection after an action does not prove emission
|
|
72
|
+
after it, or causality. No implicit action-window filtering is applied.
|
|
73
|
+
|
|
74
|
+
Existing payloads, image blocks, and log blocks remain available. Snapshot evidence
|
|
75
|
+
sits alongside `raw` and `semantic`. Android ADB and supported iOS simulators share
|
|
76
|
+
this contract; existing provider limitations still apply. `trace_context` defaults
|
|
77
|
+
to `{ "supported": false, "trace_id": null, "markers": [] }`. Journeys explicitly
|
|
78
|
+
linked to an active Android [system trace](system-traces.md) and their steps expose
|
|
79
|
+
`{ "supported": true, "trace_id": "…", "markers": [] }`; association does not align
|
|
80
|
+
clocks or inject device markers.
|
|
81
|
+
Correlation history stores identifiers, scope, timing, and ordering only, without
|
|
82
|
+
captured content, arguments, persistence, or telemetry.
|