mobile-debug-mcp 0.35.0 → 0.36.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/.cursor-plugin/marketplace.json +1 -1
- package/.github/workflows/ci.yml +1 -1
- package/README.md +86 -24
- package/agent-plugin/.antigravity-plugin/README.md +48 -0
- package/agent-plugin/.antigravity-plugin/plugin.json +18 -0
- package/agent-plugin/.claude-plugin/plugin.json +2 -2
- package/agent-plugin/.codex-plugin/plugin.json +1 -1
- package/agent-plugin/.cursor-plugin/plugin.json +2 -2
- package/agent-plugin/.mcp.json +1 -1
- package/agent-plugin/README.md +37 -8
- package/agent-plugin/cursor/.cursor-plugin/plugin.json +23 -0
- package/agent-plugin/cursor/LICENSE +201 -0
- package/agent-plugin/cursor/README.md +9 -0
- package/agent-plugin/cursor/skills/mobile-debug-mcp/SKILL.md +253 -0
- package/agent-plugin/mcp.json +1 -1
- package/agent-plugin/mcp_config.json +13 -0
- package/agent-plugin/plugin.json +1 -1
- package/agent-plugin/skills/mobile-debug-mcp/SKILL.md +36 -16
- package/dist/debugger/guard.js +4 -4
- package/dist/debugger/ios-worker.js +62 -0
- package/dist/debugger/ios.js +57 -0
- package/dist/debugger/sessions.js +33 -16
- package/dist/debugger/worker.js +6 -4
- package/dist/interact/index.js +12 -2
- package/dist/manage/ios.js +2 -0
- package/dist/observe/ios-trace/artifact.js +63 -0
- package/dist/observe/ios-trace/capabilities.js +86 -0
- package/dist/observe/ios-trace/native.js +93 -0
- package/dist/observe/ios-trace/notification.js +35 -0
- package/dist/observe/ios-trace/process.js +98 -0
- package/dist/observe/ios-trace/sessions.js +244 -0
- package/dist/observe/readiness-service.js +1 -1
- package/dist/observe/readiness.js +4 -4
- package/dist/observe/system-trace-error.js +7 -0
- package/dist/observe/system-trace-router.js +81 -0
- package/dist/observe/system-trace.js +4 -8
- package/dist/server/handlers/debugger-handlers.js +27 -8
- package/dist/server/handlers/diagnostic.js +12 -4
- package/dist/server/handlers/tool-handlers.js +19 -9
- package/dist/server/schemas/debugger-schema.js +10 -7
- package/dist/server/schemas/system-trace-schema.js +14 -9
- package/dist/server-core.js +1 -1
- package/dist/server.js +4 -4
- package/dist/utils/ios/utils.js +3 -0
- package/docs/CHANGELOG.md +23 -1
- package/docs/agent-plugin-installation-verification.md +39 -0
- package/docs/code-structure.md +3 -1
- package/docs/specs/031-ios-system-traces/intent.md +38 -0
- package/docs/specs/031-ios-system-traces/investigation.md +92 -0
- package/docs/specs/031-ios-system-traces/late-run-failure-evidence.json +32 -0
- package/docs/specs/031-ios-system-traces/plan.md +138 -0
- package/docs/specs/031-ios-system-traces/pr102-monitor-evidence.json +22 -0
- package/docs/specs/031-ios-system-traces/simulator-evidence.json +47 -0
- package/docs/specs/031-ios-system-traces/spec.md +135 -0
- package/docs/specs/032-ios-runtime-debugger/evidence.json +176 -0
- package/docs/specs/032-ios-runtime-debugger/intent.md +38 -0
- package/docs/specs/032-ios-runtime-debugger/plan.md +95 -0
- package/docs/specs/032-ios-runtime-debugger/report.md +205 -0
- package/docs/specs/032-ios-runtime-debugger/spec.md +153 -0
- package/docs/tools/TOOLS.md +2 -2
- package/docs/tools/debugger.md +45 -5
- package/docs/tools/system-traces.md +81 -14
- package/package.json +2 -1
- package/scripts/agent-plugin.mjs +55 -5
- package/src/debugger/android.ts +1 -1
- package/src/debugger/guard.ts +5 -5
- package/src/debugger/ios-worker.ts +49 -0
- package/src/debugger/ios.ts +45 -0
- package/src/debugger/lldb/breakpoints.py +51 -0
- package/src/debugger/lldb/inspection.py +109 -0
- package/src/debugger/lldb/worker.py +203 -0
- package/src/debugger/sessions.ts +24 -12
- package/src/debugger/worker.ts +7 -4
- package/src/interact/index.ts +13 -2
- package/src/manage/ios.ts +2 -0
- package/src/observe/ios-trace/artifact.ts +55 -0
- package/src/observe/ios-trace/capabilities.ts +74 -0
- package/src/observe/ios-trace/native.ts +72 -0
- package/src/observe/ios-trace/notification.ts +30 -0
- package/src/observe/ios-trace/process.ts +82 -0
- package/src/observe/ios-trace/sessions.ts +204 -0
- package/src/observe/readiness-service.ts +1 -1
- package/src/observe/readiness.ts +4 -4
- package/src/observe/system-trace-error.ts +3 -0
- package/src/observe/system-trace-router.ts +61 -0
- package/src/observe/system-trace.ts +4 -4
- package/src/server/handlers/debugger-handlers.ts +28 -9
- package/src/server/handlers/diagnostic.ts +11 -4
- package/src/server/handlers/tool-handlers.ts +20 -9
- package/src/server/schemas/debugger-schema.ts +10 -7
- package/src/server/schemas/system-trace-schema.ts +15 -9
- package/src/server-core.ts +1 -1
- package/src/server.ts +3 -3
- package/src/utils/ios/utils.ts +3 -0
- package/test/device/automated/debugger/runtime.ios.test.ts +221 -0
- package/test/device/automated/observe/ios-system-trace.smoke.ts +119 -0
- package/test/fixtures/contracts/tool-definitions.json +192 -32
- package/test/fixtures/ios-debugger-app/Main.swift +95 -0
- package/test/fixtures/ios-debugger-app/README.md +27 -0
- package/test/fixtures/ios-debugger-app/build.ts +21 -0
- package/test/helpers/ios-trace-shutdown.ts +29 -0
- package/test/unit/debugger/handle-guards.test.ts +88 -0
- package/test/unit/debugger/ios-preparation.test.ts +57 -0
- package/test/unit/debugger/ios.test.ts +104 -0
- package/test/unit/debugger/lldb-worker.py +166 -0
- package/test/unit/debugger/lldb-worker.test.ts +10 -0
- package/test/unit/observe/ios-trace-native.test.ts +90 -0
- package/test/unit/observe/ios-trace-sessions.test.ts +131 -0
- package/test/unit/observe/readiness.test.ts +1 -1
- package/test/unit/observe/system-trace-router.test.ts +49 -0
- package/test/unit/quality/agent-plugin-export.test.ts +38 -0
- package/test/unit/server/system-trace.test.ts +12 -3
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
# iOS system traces — proposed specification
|
|
2
|
+
|
|
3
|
+
2026-11-04. **Approved** by the user's second “ok” in this chat, responding to
|
|
4
|
+
the complete specification and implementation approval request.
|
|
5
|
+
[Intent](intent.md) approved by the user's “ok” in this chat.
|
|
6
|
+
Source: [issue #78](https://github.com/clivejefferies/mobile-debug-tools/issues/78).
|
|
7
|
+
[Native investigation and limits](investigation.md).
|
|
8
|
+
|
|
9
|
+
## Supported scope
|
|
10
|
+
|
|
11
|
+
Extend the existing five system-trace tools with an Instruments backend on macOS
|
|
12
|
+
with full Xcode. Initial supported combination: booted iOS simulator and Time
|
|
13
|
+
Profiler, attached to an already running development app. Baseline is Xcode 27.2
|
|
14
|
+
and iOS 26.4.1. Other versions require successful prerequisite checks and artifact
|
|
15
|
+
validation; installed templates alone do not establish support.
|
|
16
|
+
|
|
17
|
+
System Trace is discoverable but not enabled initially: the simulator probe did
|
|
18
|
+
not establish scheduling data. Animation Hitches is unsupported on the tested
|
|
19
|
+
simulator. Hangs is an instrument within Time Profiler here, not a selectable
|
|
20
|
+
standalone template; do not promise detected hangs. Physical-device capture is
|
|
21
|
+
explicitly unsupported in this initial release, with verification unrun because
|
|
22
|
+
no device is available. Report pairing, Developer Mode, signing/profiling and
|
|
23
|
+
symbol prerequisites as applicable setup guidance, never as completed checks.
|
|
24
|
+
Expanding this matrix requires evidence and a specification revision.
|
|
25
|
+
|
|
26
|
+
No host recording, all-processes mode, custom templates, app launching, automatic
|
|
27
|
+
diagnosis, summaries, arbitrary queries, or public export API. Android retains
|
|
28
|
+
its existing preset, inputs, results and verification requirements.
|
|
29
|
+
|
|
30
|
+
## Tools and contracts
|
|
31
|
+
|
|
32
|
+
Keep existing names and strict schemas. Extend capabilities and start inputs with
|
|
33
|
+
optional `appId` (nonblank bundle identifier) and `template` enum
|
|
34
|
+
`System Trace | Time Profiler | Animation Hitches | Hangs`. These fields are
|
|
35
|
+
iOS-only; reject them on Android. iOS start requires explicit `deviceId` and
|
|
36
|
+
`appId`; omitted template defaults to Time Profiler. Capabilities require explicit
|
|
37
|
+
`deviceId` on iOS; `appId` optionally probes running-app readiness. Duration stays
|
|
38
|
+
1,000–120,000 ms, default 30,000. Controls still accept only `traceId`.
|
|
39
|
+
|
|
40
|
+
iOS capabilities return `backend:xctrace`, resolved simulator/device metadata,
|
|
41
|
+
Xcode version, discovered templates, per-template support/reasons/coverage,
|
|
42
|
+
prerequisite states (`available`, `missing`, `unknown`), and actionable recovery.
|
|
43
|
+
Discovery starts no recording and grants no permissions. Distinguish unavailable
|
|
44
|
+
tooling/target, unsupported matrix, app not running, permission failure and checks
|
|
45
|
+
that only a recording can establish. Do not label unknown permissions as granted.
|
|
46
|
+
|
|
47
|
+
Reuse session state, completion reasons, IDs, host bounds, cleanup and correlation
|
|
48
|
+
fields. Extend result unions to iOS, `backend:xctrace`, and artifact
|
|
49
|
+
`format:instruments` with absolute `.trace` path, recursive `size_bytes`, and
|
|
50
|
+
`kind:directory|file`. Include pinned `app_id`, PID, executable identity,
|
|
51
|
+
selected template, target type, warnings and validation result. Never return raw
|
|
52
|
+
trace data. Unreached fields are null. Errors use existing MCP `isError` and
|
|
53
|
+
TRACE_* codes; bounded reason/recovery values distinguish setup, permission,
|
|
54
|
+
target disconnect, readiness, export and storage failures without raw stderr.
|
|
55
|
+
|
|
56
|
+
Resolve bundle identity to one current executable/PID on the pinned simulator;
|
|
57
|
+
ambiguous/missing identity fails. Always pass `--device <UDID>` and revalidate
|
|
58
|
+
identity before starting. Do not retry against a different process/name, template,
|
|
59
|
+
device or host. Exported target UUID, PID and template must match the session.
|
|
60
|
+
|
|
61
|
+
## Lifecycle, limits and privacy
|
|
62
|
+
|
|
63
|
+
Use uniquely owned mode-0700 temporary directories and fixed argument arrays.
|
|
64
|
+
Spawn the recorder with `--time-limit`, unique output and unique
|
|
65
|
+
`--notify-tracing-started` notification. Register an owned Darwin-notification
|
|
66
|
+
listener before spawning; return recording only after that notification while
|
|
67
|
+
the recorder remains live. Console “Starting recording” alone is insufficient.
|
|
68
|
+
Notification helper availability is a prerequisite, never a silent fallback.
|
|
69
|
+
|
|
70
|
+
Allow 35 seconds for readiness, 30 seconds for graceful stop/finalisation and
|
|
71
|
+
30 seconds for validation. Bound every child process and cap captured diagnostic
|
|
72
|
+
output. At requested duration, reconcile and finalise automatically. SIGINT only
|
|
73
|
+
the session-owned recorder; after its grace deadline terminate that owned child
|
|
74
|
+
and report failure/partial output. Never signal the app, by process name, or an
|
|
75
|
+
unrelated Instruments recording. On server shutdown cancel owned sessions under
|
|
76
|
+
one 10-second overall deadline; forced cleanup may leave an unreadable artifact
|
|
77
|
+
and must report that. Crashes provide no cleanup guarantee; no restart-wide sweep.
|
|
78
|
+
|
|
79
|
+
Share the existing one-session-per-device, four-active-session server limit across
|
|
80
|
+
backends. Serialise controls; retain 100 terminal metadata records for ten minutes.
|
|
81
|
+
Stale/other-server IDs fail. Completed controls are idempotent. Disconnect,
|
|
82
|
+
premature recorder exit and journey failure have explicit outcomes; journey failure
|
|
83
|
+
does not cancel capture. Retry validation only on an existing finalised owned
|
|
84
|
+
bundle, never restart recording. Cancel removes owned partial output; completed
|
|
85
|
+
artifacts remain user-managed.
|
|
86
|
+
|
|
87
|
+
Poll recursive output size every second; stop/discard on exceeding 256 MiB per
|
|
88
|
+
iOS session, reject starts with less than 1 GiB free in its output filesystem.
|
|
89
|
+
Finalisation can temporarily overshoot the polling threshold: report this as a
|
|
90
|
+
soft bound, reject oversized final output and remove it. No symlink traversal.
|
|
91
|
+
Apply restrictive permissions recursively before returning validated output.
|
|
92
|
+
Instruments may contain system-wide metadata, paths, symbols, logs and signposts
|
|
93
|
+
despite app attachment. Disclose this in tool/skill documentation. No upload,
|
|
94
|
+
telemetry or permission bypass, including `--no-prompt`. User handles any required
|
|
95
|
+
OS permissions outside the tool.
|
|
96
|
+
|
|
97
|
+
## Artifact and journey evidence
|
|
98
|
+
|
|
99
|
+
Require successful recorder exit, nonempty bounded output, parseable
|
|
100
|
+
`xctrace export --toc`, matching target/app/template metadata, expected
|
|
101
|
+
`time-sample` schema and successful table export. Record row count, including zero;
|
|
102
|
+
zero samples means no CPU sample evidence, not diagnosed inactivity. Do not call
|
|
103
|
+
a failed recording valid merely because a readable partial bundle exists.
|
|
104
|
+
Expose warnings and unavailable instruments; do not claim symbolication unless
|
|
105
|
+
verified. Validation exports are private temporary data removed after validation.
|
|
106
|
+
|
|
107
|
+
Keep `run_journey.systemTraceId` explicit. Validate active same-server,
|
|
108
|
+
same-platform/same-UDID session before any journey input. Link journey and step
|
|
109
|
+
evidence through existing trace context and correlation IDs. The trace pins the
|
|
110
|
+
profiled app; journey actions retain their existing targeting semantics and may
|
|
111
|
+
leave that app. Report that limitation. Duration expiry or stop during the journey
|
|
112
|
+
means partial coverage. Host capture bounds and unknown device-clock alignment
|
|
113
|
+
establish association only; no device markers or causal inference.
|
|
114
|
+
|
|
115
|
+
## Acceptance and verification
|
|
116
|
+
|
|
117
|
+
1. Capability matrix and rejected inputs are side-effect-free, with exact target
|
|
118
|
+
and actionable prerequisite reasons; unknown permissions stay unknown.
|
|
119
|
+
2. Updated-server simulator Time Profiler start → existing fixture journey tapping
|
|
120
|
+
Show loader and asserting Done → stop yields matching IDs, target/app metadata,
|
|
121
|
+
notification-before-input evidence, readable bundle and exported sample rows.
|
|
122
|
+
3. Deterministic checks cover stale/mismatched IDs preventing all input, ownership,
|
|
123
|
+
concurrency, expiry, cancellation, partial coverage, disconnect, identity races,
|
|
124
|
+
notification/start/stop/export/storage failures, retries and shutdown cleanup.
|
|
125
|
+
4. Real simulator checks cover explicit stop, expiry, cancellation and failed
|
|
126
|
+
journey; unavailable physical/failure-injection evidence is separate from mocks.
|
|
127
|
+
5. Existing Android traces and untraced journeys pass regression checks. Run
|
|
128
|
+
`npm run verify`, applicable `npm run test:device`, and focused updated-server
|
|
129
|
+
calls; report actual suite coverage and unrun platforms.
|
|
130
|
+
|
|
131
|
+
Affected: trace sessions/adapters/types, schemas/registration/handlers, journey and
|
|
132
|
+
evidence integration, shutdown, tests/goldens, tool docs, README, changelog and
|
|
133
|
+
packaged usage skill. Main implementation risks remain notification readiness,
|
|
134
|
+
reliable app identity resolution and finalisation deadlines; feasibility probes
|
|
135
|
+
do not establish these acceptance criteria.
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
{
|
|
2
|
+
"date": "2026-11-04",
|
|
3
|
+
"status": "PASS",
|
|
4
|
+
"transport": "MCP stdio",
|
|
5
|
+
"runtime": "v23.11.0",
|
|
6
|
+
"deviceId": "F9243BAF-62A8-4990-8A99-17F527F56FDA",
|
|
7
|
+
"server_sha256": "6a00a33d994a449ecbb54d5dbf894780f48a1c0e5a89fc871b91dd7048f4ecdc",
|
|
8
|
+
"source_sha256": "295ff0f30f5670530f9cdd7073b958917c1c574ccca9c7b921e295d0d902b699",
|
|
9
|
+
"xcode": "Xcode 27.2\nBuild version 27B52",
|
|
10
|
+
"lldb": "lldb-2103.0.34.407\nApple Swift version 6.4.2 (swiftlang-6.4.2.1.9 clang-2100.4.1.1)",
|
|
11
|
+
"fixture": "test/fixtures/ios-debugger-app/Main.swift",
|
|
12
|
+
"fixture_triggers": "Atomic command file; installed idb HID backend unavailable; not proof of successful MCP tap injection",
|
|
13
|
+
"extended_pause_expiry": true,
|
|
14
|
+
"process_exit": true,
|
|
15
|
+
"server_shutdown_recovery": true,
|
|
16
|
+
"tests_sha256": "37fbda265b5735b1b826aa448aa937359c45db0e55f8f1998a169b1aa3073acc",
|
|
17
|
+
"observations": [
|
|
18
|
+
{
|
|
19
|
+
"reason": "breakpoint",
|
|
20
|
+
"line": 49,
|
|
21
|
+
"method": "DebuggerFixture.Controller.calculate() -> ()"
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
"reason": "step",
|
|
25
|
+
"line": 8,
|
|
26
|
+
"method": "DebuggerFixture.helper(Swift.Int) -> Swift.Int"
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
"reason": "step",
|
|
30
|
+
"line": 9,
|
|
31
|
+
"method": "DebuggerFixture.helper(Swift.Int) -> Swift.Int"
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
"reason": "step",
|
|
35
|
+
"line": 49,
|
|
36
|
+
"method": "DebuggerFixture.Controller.calculate() -> ()"
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
"reason": "breakpoint",
|
|
40
|
+
"line": 20,
|
|
41
|
+
"method": "(1) suspend resume partial function for DebuggerFixture.AsyncWork.calculate(Swift.Int) async -> Swift.Int"
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
"reason": "breakpoint",
|
|
45
|
+
"line": 21,
|
|
46
|
+
"method": "(3) suspend resume partial function for DebuggerFixture.AsyncWork.calculate(Swift.Int) async -> Swift.Int"
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
"reason": "breakpoint",
|
|
50
|
+
"line": 20,
|
|
51
|
+
"method": "(1) suspend resume partial function for DebuggerFixture.AsyncWork.calculate(Swift.Int) async -> Swift.Int"
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
"reason": "step",
|
|
55
|
+
"line": 21,
|
|
56
|
+
"method": "(3) suspend resume partial function for DebuggerFixture.AsyncWork.calculate(Swift.Int) async -> Swift.Int"
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
"reason": "breakpoint",
|
|
60
|
+
"line": 66,
|
|
61
|
+
"method": "(3) suspend resume partial function for closure #1 () async -> () in DebuggerFixture.Controller.startCancellation() -> ()"
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
"reason": "breakpoint",
|
|
65
|
+
"line": 49,
|
|
66
|
+
"method": "DebuggerFixture.Controller.calculate() -> ()"
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
"reason": "breakpoint",
|
|
70
|
+
"line": 49,
|
|
71
|
+
"method": "DebuggerFixture.Controller.calculate() -> ()"
|
|
72
|
+
}
|
|
73
|
+
],
|
|
74
|
+
"locals": [
|
|
75
|
+
[
|
|
76
|
+
{
|
|
77
|
+
"name": "known",
|
|
78
|
+
"type": "Swift.Int",
|
|
79
|
+
"value": "41"
|
|
80
|
+
}
|
|
81
|
+
],
|
|
82
|
+
[
|
|
83
|
+
{
|
|
84
|
+
"name": "seed",
|
|
85
|
+
"type": "Swift.Int",
|
|
86
|
+
"value": "42"
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
"name": "known",
|
|
90
|
+
"type": "Swift.Int",
|
|
91
|
+
"value": "42"
|
|
92
|
+
}
|
|
93
|
+
],
|
|
94
|
+
[
|
|
95
|
+
{
|
|
96
|
+
"name": "seed",
|
|
97
|
+
"type": "Swift.Int",
|
|
98
|
+
"value": "42"
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
"name": "known",
|
|
102
|
+
"type": "Swift.Int",
|
|
103
|
+
"value": "42"
|
|
104
|
+
},
|
|
105
|
+
{
|
|
106
|
+
"name": "after",
|
|
107
|
+
"type": "Swift.Int",
|
|
108
|
+
"value": "43"
|
|
109
|
+
}
|
|
110
|
+
],
|
|
111
|
+
[
|
|
112
|
+
{
|
|
113
|
+
"name": "cancelled",
|
|
114
|
+
"type": "Swift.Bool",
|
|
115
|
+
"value": "true"
|
|
116
|
+
}
|
|
117
|
+
]
|
|
118
|
+
],
|
|
119
|
+
"async_boundary_step": {
|
|
120
|
+
"expected_line": 21,
|
|
121
|
+
"observed": {
|
|
122
|
+
"source_file": "test/fixtures/ios-debugger-app/Main.swift",
|
|
123
|
+
"line": 21,
|
|
124
|
+
"method_name": "(3) suspend resume partial function for DebuggerFixture.AsyncWork.calculate(Swift.Int) async -> Swift.Int",
|
|
125
|
+
"class_name": null
|
|
126
|
+
}
|
|
127
|
+
},
|
|
128
|
+
"assertions": [
|
|
129
|
+
"Exact source binding and pending source creation",
|
|
130
|
+
"Known primitive locals",
|
|
131
|
+
"Into/over/out",
|
|
132
|
+
"Stop/frame stale rejection",
|
|
133
|
+
"Paused tap rejected before dispatch",
|
|
134
|
+
"Paused readiness without UI acquisition",
|
|
135
|
+
"Cancelled event wait preserves session",
|
|
136
|
+
"Before/after await values and nested async child",
|
|
137
|
+
"Step over await reaches after-await source line",
|
|
138
|
+
"Task cancellation and fresh Task cancelled UI",
|
|
139
|
+
"Real 60-second pause expiry and fresh result UI",
|
|
140
|
+
"Target self-exit, disconnected state and complete cleanup",
|
|
141
|
+
"Idempotent detach with no remaining resources",
|
|
142
|
+
"Server shutdown while paused then independent UI recovery"
|
|
143
|
+
],
|
|
144
|
+
"unrun": [
|
|
145
|
+
"physical iOS devices",
|
|
146
|
+
"other Xcode/Swift versions",
|
|
147
|
+
"optimized apps",
|
|
148
|
+
"installed/published package",
|
|
149
|
+
"forced host termination",
|
|
150
|
+
"real device disconnect",
|
|
151
|
+
"live idle/absolute expiry",
|
|
152
|
+
"late-loaded-image binding"
|
|
153
|
+
],
|
|
154
|
+
"scope": "Focused real MCP iOS simulator debugger journey, including extended pause expiry",
|
|
155
|
+
"repository_verification": {
|
|
156
|
+
"status": "PASS",
|
|
157
|
+
"unit_files": 96,
|
|
158
|
+
"command": "npm run verify"
|
|
159
|
+
},
|
|
160
|
+
"broader_device_suite": {
|
|
161
|
+
"status": "FAIL",
|
|
162
|
+
"observations": [
|
|
163
|
+
"Initial Android interaction SDK timeout; isolated unchanged retry passed",
|
|
164
|
+
"Retry failed Android Perfetto shutdown-artifact assertion; isolated baseline and current checks passed"
|
|
165
|
+
],
|
|
166
|
+
"root_cause": "unestablished",
|
|
167
|
+
"full_suite_pass_claimed": false
|
|
168
|
+
},
|
|
169
|
+
"cleanup": {
|
|
170
|
+
"ios_simulator": "restored to initial shutdown state",
|
|
171
|
+
"swift_fixture_build_directories_remaining": 0,
|
|
172
|
+
"owned_adb_forwards_remaining": 0,
|
|
173
|
+
"owned_perfetto_artifacts_remaining": 0,
|
|
174
|
+
"unrelated_installed_fixtures": "preserved"
|
|
175
|
+
}
|
|
176
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# iOS runtime debugger — intent
|
|
2
|
+
|
|
3
|
+
- Source: [issue #70](https://github.com/clivejefferies/mobile-debug-tools/issues/70), and the user's 2026-11-04 request to take the next Ready ticket with Android-equivalent functionality, including async debugging.
|
|
4
|
+
- Originator: user in this chat.
|
|
5
|
+
- Captured: 2026-11-04.
|
|
6
|
+
- Status: intent approved by the user's “ok” on 2026-11-04 in response to the scope and approval request in this chat. Specification also approved in this chat on 2026-11-04; see spec.md. Issue #70 matches the roadmap and current branch; Ready-column membership could not be checked because GitHub authentication lacks `read:project`.
|
|
7
|
+
|
|
8
|
+
## Problem and outcome
|
|
9
|
+
|
|
10
|
+
MCP clients can debug Android development apps but lack equivalent iOS runtime
|
|
11
|
+
inspection. Add an LLDB-backed debugger for iOS simulator development apps,
|
|
12
|
+
reusing the existing debugger tools and session/evidence conventions where
|
|
13
|
+
appropriate. Support attach, source breakpoints and events, bounded stacks and
|
|
14
|
+
shallow locals, stepping, resume and detach, with explicit capabilities and
|
|
15
|
+
actionable setup failures.
|
|
16
|
+
|
|
17
|
+
## Async parity and success
|
|
18
|
+
|
|
19
|
+
Verify a deterministic Swift concurrency fixture with source stops and useful
|
|
20
|
+
locals before and after `await`, resumed execution, nested task work, task
|
|
21
|
+
cancellation and application recovery. Assess stepping across suspension and
|
|
22
|
+
report its observed limits. Android's existing coroutine assessment establishes
|
|
23
|
+
execution inspection, not reconstruction of suspended tasks or logical async
|
|
24
|
+
stacks; distinguish those capabilities explicitly on iOS too.
|
|
25
|
+
|
|
26
|
+
Preserve stale-reference rejection, pause-aware interaction guards, bounded
|
|
27
|
+
waits/cancellation, session isolation, expiry and owned cleanup. Prove the journey
|
|
28
|
+
through actual MCP calls and independent fixture outcomes, and retain Android
|
|
29
|
+
regression coverage. Report unavailable environments honestly.
|
|
30
|
+
|
|
31
|
+
## Constraints and questions
|
|
32
|
+
|
|
33
|
+
Physical-device support follows separately. Evaluation, mutation, arbitrary LLDB
|
|
34
|
+
commands and generic suspended-task reconstruction are excluded from this initial
|
|
35
|
+
scope. Inspect LLDB/Xcode support for async frames and stepping before proposing
|
|
36
|
+
the exact capability contract. Debug values remain bounded and sensitive; avoid
|
|
37
|
+
persisting app data in public evidence. Specification approval follows intent
|
|
38
|
+
acceptance under the repository process.
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
# iOS runtime debugger — implementation and verification
|
|
2
|
+
|
|
3
|
+
Scope: [intent](intent.md) and [specification](spec.md), both approved by the user
|
|
4
|
+
on 2026-11-04. Use the repository MCP Builder and Test Authoring skills.
|
|
5
|
+
|
|
6
|
+
## Implementation
|
|
7
|
+
|
|
8
|
+
- [x] Establish LLDB Python loading and explicit simulator/process attribution.
|
|
9
|
+
- [x] Add structured LLDB worker, safe inspection, exact breakpoints and watchdogs.
|
|
10
|
+
- [x] Reuse session lifecycle with platform-specific native/worker configuration;
|
|
11
|
+
update schemas, dispatch, diagnostics, guards and readiness.
|
|
12
|
+
- [x] Add deterministic Swift simulator fixture and MCP runtime/async journeys.
|
|
13
|
+
- [x] Add contract, identity, lifecycle and guard regression tests; update tool
|
|
14
|
+
compatibility golden only for approved schema changes.
|
|
15
|
+
- [x] Align debugger guide, tool reference, README, changelog and packaging.
|
|
16
|
+
- [x] Review diff, execute required verification and record actual results below.
|
|
17
|
+
Full-suite success remains unestablished; see the failed checks below.
|
|
18
|
+
|
|
19
|
+
## Verification matrix
|
|
20
|
+
|
|
21
|
+
| Spec criterion | Check |
|
|
22
|
+
| --- | --- |
|
|
23
|
+
| Core runtime flow | `MCP_IOS_DEBUGGER_DEVICE=<UDID> node --import tsx test/device/automated/debugger/runtime.ios.test.ts` through built stdio server |
|
|
24
|
+
| Async/cancellation | Same journey with controlled before/after-await values, nested work, cancellation and fresh UI assertions; separate step-boundary result |
|
|
25
|
+
| Identity, failure, references and guards | Focused `test/unit/debugger/*.test.ts`, simulator invalid PID/foreign target, stale frame/stop, guarded input/readiness, event cancellation and detach |
|
|
26
|
+
| Expiry and shutdown | Worker watchdog unit checks plus real pause expiry and server EOF cleanup in fixture journey |
|
|
27
|
+
| Contract/Android regression | `npm run verify`; existing runtime, Kotlin and coroutine Android MCP checks on explicit emulator |
|
|
28
|
+
| Broader device compatibility | `npm run test:device` with selected targets; report the actual covered platforms and skipped prerequisites |
|
|
29
|
+
|
|
30
|
+
Required: Node 22+, installed Xcode 27.2/Swift 6.4.2/LLDB 2103.0.34.407,
|
|
31
|
+
simulator runtime, development fixture compiled with debug metadata and no
|
|
32
|
+
optimisation. Android regressions require existing JDK/SDK/Kotlin dependencies.
|
|
33
|
+
No physical-device iOS support is claimed. Hosted CI is separate from local checks.
|
|
34
|
+
|
|
35
|
+
Select existing simulator F9243BAF-62A8-4990-8A99-17F527F56FDA (iPhone 17 Pro,
|
|
36
|
+
iOS 26.4), initially shut down. Boot it for the fixture; preserve existing apps
|
|
37
|
+
and settings, install/remove only fixture-owned app/build files, detach owned
|
|
38
|
+
debuggers, and restore the initial shutdown state. Record exact server/fixture
|
|
39
|
+
hashes, observed stops/locals, independent UI state and cleanup. Simulator access
|
|
40
|
+
requires outside-sandbox native commands; the authorised inventory read succeeded.
|
|
41
|
+
If a prerequisite is unavailable, retain the acceptance criterion and record a
|
|
42
|
+
concrete blocker. Do not treat mock/native readiness checks as live verification.
|
|
43
|
+
|
|
44
|
+
## Results
|
|
45
|
+
|
|
46
|
+
- **PASS** `npm run verify`: lint/quality/architecture, build, all 96 unit files,
|
|
47
|
+
plugin consistency, Node 23.11.0. Log `/tmp/ios-debugger-final-verify.log`.
|
|
48
|
+
- **PASS** `MCP_IOS_DEBUGGER_DEVICE=F9243BAF-62A8-4990-8A99-17F527F56FDA MCP_IOS_DEBUGGER_EXTENDED=1 node --import tsx test/device/automated/debugger/runtime.ios.test.ts`.
|
|
49
|
+
Exact stable-build hash, stops, locals and asserted cleanup/recovery are in
|
|
50
|
+
[evidence.json](evidence.json). No HID success is inferred from fixture control.
|
|
51
|
+
- **PASS** focused Android runtime, Kotlin locals and coroutine MCP regressions
|
|
52
|
+
using the existing fixture/compiler dependencies. The broader suite also reran
|
|
53
|
+
the final Android runtime debugger successfully.
|
|
54
|
+
- **PASS** unchanged standalone iOS screenshot, log and UI-tree smoke checks.
|
|
55
|
+
- **PASS** package dry-run contents, plugin generation/consistency and diff/link
|
|
56
|
+
checks. No publication or installed-package verification occurred.
|
|
57
|
+
- **FAIL** broader `ADB_PATH=/Users/clivejefferies/Library/Android/sdk/platform-tools/adb MCP_DEBUGGER_DEVICE=emulator-5554 npm run test:device`: initial Android
|
|
58
|
+
interaction request timeout; focused unchanged retry passed. The full-suite
|
|
59
|
+
retry passed that branch and both-platform observations/correlated evidence,
|
|
60
|
+
then failed Android Perfetto active-shutdown artifact removal. The isolated
|
|
61
|
+
Perfetto check passed on both unchanged HEAD and current build. These failures
|
|
62
|
+
remain unreproduced and unexplained; no full-suite pass is claimed.
|
|
63
|
+
- Full-suite opt-in Kotlin/coroutine/iOS debugger checks were **UNRUN** in that
|
|
64
|
+
invocation; each passed its separate focused run above. iOS system tracing was
|
|
65
|
+
**UNRUN** (no `IOS_SYSTEM_TRACE_DEVICE` supplied); it is outside this feature.
|
|
66
|
+
- **PASS** owned cleanup: no MCP device trace files or ADB forwards remained;
|
|
67
|
+
debugger/coroutine packages and Swift build directories removed. Unrelated
|
|
68
|
+
fixtures preserved; iOS simulator restored to shutdown; Android emulator left
|
|
69
|
+
running. Temporary baseline source/build copy removed.
|
|
70
|
+
|
|
71
|
+
See [verification report](report.md) for evidence boundaries, resolved findings,
|
|
72
|
+
unrun variants and original failed observations.
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
## PR #103 review repair
|
|
76
|
+
|
|
77
|
+
- [x] Cache shared iOS preparation and reset rejected preparation for retry.
|
|
78
|
+
- [x] Add fake-toolchain coverage for concurrent reuse, retry and worker creation.
|
|
79
|
+
- [x] Check real Xcode cached preparation and rerun the focused iOS MCP journey.
|
|
80
|
+
- [x] Complete quiet repository verification (97 unit files); publish the repair to PR #103.
|
|
81
|
+
|
|
82
|
+
See the [report follow-up](report.md#pr-103-preparation-cache-follow-up--2026-11-04)
|
|
83
|
+
for exact evidence and retained broader-suite limitations.
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
## PR #103 stored-handle pause guard repair
|
|
87
|
+
|
|
88
|
+
- [x] Validate guard targets through the stored-handle execution lookup.
|
|
89
|
+
- [x] Cover omitted/partial hints, known/racing pauses, platform/device isolation,
|
|
90
|
+
and explicit mismatches; prove regression detects the original route.
|
|
91
|
+
- [x] Run `npm run verify` (98 unit files) and the updated real iOS MCP journey.
|
|
92
|
+
- [x] Restore fixture/device state and prepare the narrow repair for PR publication.
|
|
93
|
+
|
|
94
|
+
The finding is in an outside-diff review summary, with no new inline thread to
|
|
95
|
+
resolve. See the [report](report.md) for exact evidence and retained limitations.
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
# iOS runtime debugger verification — issue #70
|
|
2
|
+
|
|
3
|
+
Date: 2026-11-04. Scope: [approved specification](spec.md).
|
|
4
|
+
Implementation: existing eleven MCP debugger tools gain the optional simulator
|
|
5
|
+
LLDB backend; Android remains on JDI. This is local source/build verification,
|
|
6
|
+
not hosted CI, an installed package, a publication or physical-device evidence.
|
|
7
|
+
|
|
8
|
+
## Environment and method
|
|
9
|
+
|
|
10
|
+
macOS, Node 23.11.0 (repository requires >=22; hosted CI selects Node 22),
|
|
11
|
+
Xcode 27.2/27B52, LLDB 2103.0.34.407 and Swift 6.4.2. Simulator:
|
|
12
|
+
F9243BAF-62A8-4990-8A99-17F527F56FDA, iPhone 17 Pro, iOS 26.4.
|
|
13
|
+
The disposable Swift fixture uses `-g -Onone`, targeting iOS 18 simulator.
|
|
14
|
+
|
|
15
|
+
The runner communicates with a freshly built stdio MCP server. It checks actual
|
|
16
|
+
source stops, stack frames and synthetic known-value locals; independent fresh
|
|
17
|
+
MCP UI-tree assertions establish completion/cancellation and recovery. It does
|
|
18
|
+
not infer logical task identity from opaque thread IDs or task/thread names.
|
|
19
|
+
|
|
20
|
+
Installed idb can read UI trees but cannot inject HID with this Xcode: its
|
|
21
|
+
SimulatorKit framework path is absent. Therefore fixture actions use a private
|
|
22
|
+
command file, delivered by atomic rename and handled by the fixture main-loop
|
|
23
|
+
timer. This is independent fixture control, not proof of successful MCP tap
|
|
24
|
+
injection. Paused MCP taps are checked for rejection before dispatch. No
|
|
25
|
+
production app instrumentation, source evaluation or security changes are used.
|
|
26
|
+
|
|
27
|
+
## Evidence and results
|
|
28
|
+
|
|
29
|
+
The final stable-build simulator journey **PASS**ed with real pause expiry enabled.
|
|
30
|
+
[Compact evidence](evidence.json) records the exact server/fixture/test hashes,
|
|
31
|
+
source stops and bounded synthetic values. Recomputing the final source/build hash
|
|
32
|
+
matched the runtime fingerprint. Log: `/tmp/ios-debugger-final.log`.
|
|
33
|
+
|
|
34
|
+
| Check | Result |
|
|
35
|
+
| --- | --- |
|
|
36
|
+
| Exact source binding; pending source; non-executable line rejection | PASS |
|
|
37
|
+
| Core stack/locals and into/over/out | PASS: known=41, fresh result=42 UI |
|
|
38
|
+
| Pause guard/readiness and stale references | PASS |
|
|
39
|
+
| Cancelled event wait and usable running session | PASS |
|
|
40
|
+
| Before/after await with nested async child and actor/main-actor transitions | PASS: known=42, after=43, fresh Async result 44 UI |
|
|
41
|
+
| Step over await | PASS: source line 20 to line 21 in the resumed partial function |
|
|
42
|
+
| Task cancellation | PASS: cancelled=true and fresh Task cancelled UI |
|
|
43
|
+
| Real 60-second pause expiry | PASS: pause_limit, complete cleanup and fresh result UI |
|
|
44
|
+
| Target process exit | PASS: disconnected state, complete cleanup and fixture relaunch |
|
|
45
|
+
| Idempotent detach and server shutdown while paused | PASS: no remaining resources; independent fresh result UI |
|
|
46
|
+
|
|
47
|
+
`npm run verify` **PASS**: lint/structural/architecture checks, TypeScript build,
|
|
48
|
+
all 96 unit files and generated plugin consistency. Log:
|
|
49
|
+
`/tmp/ios-debugger-final-verify.log`. The portable usage skill and generated Cursor
|
|
50
|
+
copy now describe the advertised iOS backend; this does not install/update a
|
|
51
|
+
connected or pinned published server.
|
|
52
|
+
|
|
53
|
+
The broader device suite passed the final Android debugger regression, then
|
|
54
|
+
**FAIL**ed on an Android interaction SDK request timeout (120000 ms); its original
|
|
55
|
+
log does not identify the call. A focused assertion-identical retry with tool-name
|
|
56
|
+
and elapsed-time logging **PASS**ed every call (approximately 47 seconds total).
|
|
57
|
+
The timeout was not reproduced and its cause is unknown; no assertion, timeout,
|
|
58
|
+
retry policy or interaction implementation was changed. Original and retry logs:
|
|
59
|
+
`/tmp/ios-debugger-device-suite.log` and
|
|
60
|
+
`/tmp/ios-debugger-interaction-retest.log`. The unchanged full-suite retry passed the Android debugger/interaction checks and
|
|
61
|
+
both-platform screenshot/log/tree/correlated-evidence checks, then **FAIL**ed the
|
|
62
|
+
last Android Perfetto active-shutdown cleanup assertion (one owned capture file
|
|
63
|
+
still existed). Log: `/tmp/ios-debugger-device-suite-retry.log`.
|
|
64
|
+
|
|
65
|
+
The same isolated Perfetto test then **PASS**ed on both unmodified HEAD
|
|
66
|
+
`8bafc318a6342cf4585621d2108353836d40f72d` (archived and compiled in a temporary
|
|
67
|
+
copy using the same dependencies) and the current build. Logs:
|
|
68
|
+
`/tmp/ios-debugger-trace-baseline.log`, `/tmp/ios-debugger-trace-current.log`.
|
|
69
|
+
This does not establish the original timeout/cleanup cause or prove it fixed.
|
|
70
|
+
No tracing source, assertion or deadline was changed; no full device-suite pass
|
|
71
|
+
is claimed. The failed check's exact owned artifact was removed through the
|
|
72
|
+
existing identity-checking trace adapter. Final checks found no MCP capture files
|
|
73
|
+
or ADB forwards. Debugger/coroutine test packages and Swift build directories were
|
|
74
|
+
removed; unrelated installed fixtures were preserved. The iOS simulator was
|
|
75
|
+
returned to its initial shutdown state; the Android emulator remains running.
|
|
76
|
+
|
|
77
|
+
Independent unchanged iOS screenshot, log and UI-tree smoke checks **PASS**ed.
|
|
78
|
+
Log: `/tmp/ios-debugger-ios-observations.log`. These establish observation delivery
|
|
79
|
+
and structure, not a layout claim or successful HID input.
|
|
80
|
+
|
|
81
|
+
The initial Android runtime, Kotlin locals and coroutine MCP regressions passed
|
|
82
|
+
on emulator-5554, Android 16/API 36. Kotlin/stdlib 2.0.21, coroutines 1.9.0 and
|
|
83
|
+
fixture JDK 17.0.11 used existing cached dependencies and `/tmp/pr96-kotlinc`.
|
|
84
|
+
The debugger uses its ordinary Android Studio JBR discovery. Raw local logs:
|
|
85
|
+
`/tmp/ios-debugger-android-regression.log`,
|
|
86
|
+
`/tmp/ios-debugger-kotlin-regression.log`,
|
|
87
|
+
`/tmp/ios-debugger-coroutine-regression.log`.
|
|
88
|
+
|
|
89
|
+
`npm pack --dry-run --json` and explicit contents assertions passed for all three
|
|
90
|
+
LLDB Python modules and compiled iOS backend modules. CI packaging assertions now
|
|
91
|
+
cover these resources. This does not establish installed-package loading.
|
|
92
|
+
|
|
93
|
+
## Findings resolved during development
|
|
94
|
+
|
|
95
|
+
- Ignore internal LLDB transitions without stopped-thread evidence; consume LLDB
|
|
96
|
+
process events before reading public process/thread snapshots.
|
|
97
|
+
- Keep fixture variables live across await. The original constant's scope had no
|
|
98
|
+
location in a resume partial function; requiring its later use preserved actual
|
|
99
|
+
`known=42` inspection. Assertions were retained, not replaced by availability.
|
|
100
|
+
- Use LLDB's invalid-line sentinel for the error-reporting StepInto overload;
|
|
101
|
+
line zero is not that sentinel. Check native step errors before acknowledging.
|
|
102
|
+
- Normalize Swift Bool static storage to textual true/false; never evaluate a
|
|
103
|
+
getter, formatter, expression or object description.
|
|
104
|
+
- Preserve known suspension when a stale/invalid step is rejected. Diagnostic
|
|
105
|
+
lifecycle fallbacks cannot bypass pause guards.
|
|
106
|
+
- Bound and reuse frame references; preserve cleanup uncertainty after lost worker
|
|
107
|
+
or process handles instead of treating process closure as confirmed release.
|
|
108
|
+
- Classify signals/exceptions separately from completed steps. A synchronous
|
|
109
|
+
`simctl terminate` probe timed out while attached; the fixture now exits itself
|
|
110
|
+
to test actual process-exit cleanup without blocking the runner on a signal stop.
|
|
111
|
+
- URL-based fixture control encountered a system confirmation. The simulator was
|
|
112
|
+
rebooted to clear this fixture-created prompt; URL control was removed. Atomic
|
|
113
|
+
file delivery avoids the timer observing a partially written command.
|
|
114
|
+
|
|
115
|
+
These failed development observations remain distinct from successful reruns;
|
|
116
|
+
none is represented as evidence that all environments or timings are covered.
|
|
117
|
+
|
|
118
|
+
## Limits and review
|
|
119
|
+
|
|
120
|
+
Physical iOS devices, other Xcode/Swift/runtime versions, optimized builds,
|
|
121
|
+
installed/published-package operation, real device disconnect, forced host kill,
|
|
122
|
+
long idle/absolute expiry and a late-loaded-image binding journey remain unrun.
|
|
123
|
+
Pause expiry is checked live; idle/absolute expiry logic also has deterministic
|
|
124
|
+
worker/host unit coverage. Pending source creation is checked independently.
|
|
125
|
+
|
|
126
|
+
Swift strings and other aggregate locals expose type/opaque reference summaries;
|
|
127
|
+
standard supported numeric/bool wrappers use static storage. Missing debug values
|
|
128
|
+
remain explicitly unavailable. No suspended-task enumeration or complete logical
|
|
129
|
+
async-stack reconstruction is exposed. Async stepping evidence is the tested
|
|
130
|
+
step-over-await route, not every Swift concurrency construct.
|
|
131
|
+
|
|
132
|
+
Focused review covers target membership/start identity, source resolution, strict
|
|
133
|
+
schema/dispatch parity, bounded IPC/inspection, stop epochs, diagnostic privacy,
|
|
134
|
+
platform guards, expiry and owned teardown. Android contract compatibility remains
|
|
135
|
+
covered by its existing fixture and unit tests; iOS scope is simulator-only.
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
## PR #103 preparation-cache follow-up — 2026-11-04
|
|
139
|
+
|
|
140
|
+
[Review comment](https://github.com/clivejefferies/mobile-debug-tools/pull/103#discussion_r4470121366)
|
|
141
|
+
identified duplicated prerequisite subprocesses during attach. Preparation now
|
|
142
|
+
shares its in-flight/successful promise per server process and clears a rejected
|
|
143
|
+
promise, preserving platform checks, readiness validation and worker configuration.
|
|
144
|
+
No tool schema, timeout or inspection behaviour changes.
|
|
145
|
+
|
|
146
|
+
- **PASS** isolated fake-toolchain regression: concurrent calls share preparation,
|
|
147
|
+
failure permits retry, successful configuration is reused, and worker creation
|
|
148
|
+
adds no extra prerequisite probes.
|
|
149
|
+
- **PASS** real Xcode preparation followed by cached reuse within a 100 ms budget;
|
|
150
|
+
no app was attached by that probe.
|
|
151
|
+
- **PASS** focused real iOS MCP runtime/async/cancellation/process-exit/shutdown
|
|
152
|
+
journey on the same simulator/toolchain. Build fingerprint:
|
|
153
|
+
`0200deeb0cff9f04b54ed929258ebd19185c8be86e2badb6cdcbfa21f798fdb1`.
|
|
154
|
+
Source fingerprint remains `295ff0f30f5670530f9cdd7073b958917c1c574ccca9c7b921e295d0d902b699`.
|
|
155
|
+
Log: `/tmp/pr103-cache-ios.log`. Extended pause expiry was not repeated for
|
|
156
|
+
this preparation-only fix; the earlier extended evidence remains above.
|
|
157
|
+
- **PASS** quiet `npm run verify`: lint/quality/architecture, build, all 97 unit
|
|
158
|
+
files and plugin consistency. Log: `/tmp/pr103-cache-verify-final.log`.
|
|
159
|
+
A prior run alongside native testing failed the unchanged conditional-action
|
|
160
|
+
timing assertion. Its isolated retry passed, as did the quiet full verification;
|
|
161
|
+
no assertion or timeout was modified. Original/retry logs:
|
|
162
|
+
`/tmp/pr103-cache-verify.log`, `/tmp/pr103-cache-conditional-retest.log`.
|
|
163
|
+
|
|
164
|
+
The regression child loads its TypeScript toolchain before platform emulation,
|
|
165
|
+
so the host retains its native compiler selection on Linux. This test-only ordering
|
|
166
|
+
adjustment also passed all 97 files in `npm run verify` (log:
|
|
167
|
+
`/tmp/pr103-cache-portable-verify.log`). The preparation fix was published in
|
|
168
|
+
`f00e9fd`, and its review thread was resolved; both hosted unit-test runs passed
|
|
169
|
+
that commit. Later PR-head checks must be assessed separately.
|
|
170
|
+
|
|
171
|
+
The broader device-suite failures above remain separate; this fix does not claim
|
|
172
|
+
that their causes were established or corrected. Simulator shutdown was restored.
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
## PR #103 stored-handle guard follow-up — 2026-11-04
|
|
176
|
+
|
|
177
|
+
[Outside-diff review finding](https://github.com/clivejefferies/mobile-debug-tools/pull/103#pullrequestreview-5772655824):
|
|
178
|
+
`tap_element` could execute on its stored iOS handle's device while the central
|
|
179
|
+
guard selected Android when platform hints were omitted. The guard now obtains
|
|
180
|
+
its target through the same handle/platform/device validation used by execution.
|
|
181
|
+
Other tool defaults remain unchanged; explicit conflicting hints still reject
|
|
182
|
+
handle use rather than retargeting input.
|
|
183
|
+
|
|
184
|
+
- **PASS** regression using real handle creation with mocked device/UI/input
|
|
185
|
+
boundaries: omitted/partial hints select the stored iOS device, known pauses
|
|
186
|
+
prevent UI reads/input, a racing pause prevents native dispatch, and unrelated
|
|
187
|
+
platforms/devices remain usable. Mismatched and missing handles retain rejection.
|
|
188
|
+
- **PASS** mutation check: restoring the original Android-default guard route
|
|
189
|
+
makes that regression fail; fixed source was restored before verification.
|
|
190
|
+
- **PASS** `npm run verify`: lint/quality/architecture, build, all 98 unit files,
|
|
191
|
+
and plugin consistency. Log: `/tmp/pr103-handle-verify.log`.
|
|
192
|
+
- **PASS** updated real simulator MCP journey: obtain an iOS handle while running,
|
|
193
|
+
stop at a source breakpoint, then call `tap_element` with only that handle and
|
|
194
|
+
controls, omitting both platform and device ID. Observed `DEBUGGER_PAUSED`,
|
|
195
|
+
`delivery_status: not_delivered`, `dispatch_started: false`, and the correct
|
|
196
|
+
iOS debugger/device metadata. This proves pause rejection, not successful HID
|
|
197
|
+
injection. The existing core/async/cancellation/process-exit/shutdown journey
|
|
198
|
+
also passed on the same Xcode/LLDB/Swift/runtime matrix.
|
|
199
|
+
|
|
200
|
+
Native build fingerprint:
|
|
201
|
+
`28e56d77b9ba4caad778c223306609c3bb284b210b1ea996b927aca47134cf55`.
|
|
202
|
+
Log: `/tmp/pr103-handle-ios.log`. No fixture source change or timeout/assertion
|
|
203
|
+
weakening was needed. Device tests were run after repository verification to keep
|
|
204
|
+
the checks separate. The fixture was removed and simulator shutdown restored.
|
|
205
|
+
The earlier broader-suite limitations remain recorded above.
|