Problem
debug symbols can symbolicate an Apple crash when the caller already has a crash artifact, but
agent-device does not provide a first-class way to discover and retrieve recent app crash reports from
the selected target. Agents must leave the command surface, use platform-specific tools, and often
paste too much crash data into context.
We need a bounded evidence workflow that discovers recent crashes, retrieves one artifact, and hands
it cleanly to the existing symbolication path.
Desired command model
Explore a narrow crash-evidence family, for example:
agent-device debug crashes list [--since ...] [--limit ...]
agent-device debug crashes get <crash-id> [--out ...]
agent-device debug symbols --artifact <retrieved-path> --dsym ...
Names are provisional. Prefer extending the existing debug family only if it stays one coherent
question; otherwise introduce a focused command family rather than growing a mixed debug namespace.
list should return compact metadata only: stable ID, app/bundle/package identity, timestamp,
platform, crash kind/signal/exception when cheaply available, process, target identity, and artifact
availability. get should copy/download one report into the session artifact store and return path,
size, checksum when available, provenance, and a bounded summary. Raw reports must never be dumped by
default.
Platform research
Document capabilities and limitations before finalizing a cross-platform contract:
- iOS simulator: inventory diagnostic reports through supported simulator/host facilities; establish
whether IDs remain stable after reboot and how app identity is filtered.
- iOS physical device: evaluate
devicectl/device diagnostics availability, pairing/developer-mode
requirements, permissions, OS/Xcode version gates, and whether retrieval can be app-scoped.
- Android emulator/physical: distinguish Java/Kotlin tombstones or logcat fatal exceptions from native
tombstones/ANRs; determine what is retrievable without root and what only exists as bounded log
evidence.
- macOS: assess user diagnostic reports and sandbox/privacy boundaries without scanning unrelated
applications by default.
- Remote/cloud providers: map provider-owned artifacts into the existing artifacts model where their
APIs expose crash reports; return typed unsupported capability otherwise.
- TV and other targets: add only evidence-backed cells. Do not infer support from a similar platform
name.
Architecture constraints
- Classify every dispatch path/platform cell in
packages/contracts/src/interaction-guarantees.ts only if this is an interaction guarantee; otherwise
use the command descriptor/capability registries that own command support. Do not manufacture parity
through command-name lists.
- All host process execution goes through
src/utils/exec.ts helpers.
- Artifacts and diagnostics use
src/daemon/session-store.ts and the existing artifact response model;
do not hand-build session paths or write ad-hoc logs.
- Errors use
normalizeError fields and typed details (reason, permission/tool/version requirements,
attempted source). No message sniffing.
- Preserve app/session scoping. Listing all host crash reports should require an explicit scope and
must not leak unrelated app names or user data in default output.
- Keep response arrays and summaries bounded. Full artifacts stay on disk/provider storage and are
referenced by path/handle.
- Existing
debug symbols remains the symbolication owner. Retrieval should compose with it rather
than duplicate UUID matching, frame parsing, or dSYM search.
- Declare timeout, batching, MCP exposure, result typing, and platform capability on the command
descriptor surface. Add an MCP outputSchema for closed result shapes.
Proposed result sketches
List result:
{
"crashes": [
{
"id": "provider-stable-id",
"occurredAt": "2026-08-16T12:00:00Z",
"app": "com.example.app",
"process": "Example",
"platform": "ios",
"kind": "exception",
"summary": "EXC_BAD_ACCESS"
}
],
"truncated": false,
"source": "platform-diagnostics"
}
Get result:
{
"crash": { "id": "provider-stable-id", "occurredAt": "...", "app": "..." },
"artifact": {
"artifactType": "crash-report",
"path": ".../crash.ips",
"sizeBytes": 12345
},
"summary": { "exception": "EXC_BAD_ACCESS", "topFrames": [] }
}
Treat these as design prompts, not wire compatibility commitments.
Verification plan
- Build a fixture corpus for Apple
.ips/.crash, Android fatal exception/ANR/native samples, and
malformed or partially written reports. Shared fixtures are named exports, not repeated literals.
- Unit-test filtering, ordering, stable ID generation, bounds, redaction, timestamp parsing, and typed
unsupported/permission failures.
- Prove list does not read or return report bodies and get retrieves only the selected ID.
- Prove the retrieved Apple artifact can be passed unchanged to
debug symbols, including matching
and mismatched dSYM cases.
- Integration-test supported simulator/emulator paths with a controlled crashing fixture app. See a
new test fail before implementation, then pass after the owning interface exists.
- Test app/session scoping with crashes from two apps and verify the default result cannot expose the
unrelated app.
- Test pagination/limit behavior and very large reports; command output remains bounded while the
artifact size is preserved accurately.
- Capability tests cover every claimed platform/kind cell and pin explicit unsupported cells with
recovery hints.
- Verify CLI text,
--json, Node result types, MCP structured content/output schema, artifact listing,
and docs/help remain aligned.
Acceptance criteria
- Agents can list recent crashes for the selected app/target without raw platform commands.
- Agents can retrieve exactly one crash as a session artifact and receive bounded structured metadata.
- Apple retrieval composes directly with
debug symbols.
- Unsupported and permission-limited targets fail with typed actionable details.
- Default output is token-bounded and privacy-scoped.
- Support claims are backed by platform fixtures/integration evidence, not nominal parity.
Problem
debug symbolscan symbolicate an Apple crash when the caller already has a crash artifact, butagent-device does not provide a first-class way to discover and retrieve recent app crash reports from
the selected target. Agents must leave the command surface, use platform-specific tools, and often
paste too much crash data into context.
We need a bounded evidence workflow that discovers recent crashes, retrieves one artifact, and hands
it cleanly to the existing symbolication path.
Desired command model
Explore a narrow crash-evidence family, for example:
Names are provisional. Prefer extending the existing
debugfamily only if it stays one coherentquestion; otherwise introduce a focused command family rather than growing a mixed debug namespace.
listshould return compact metadata only: stable ID, app/bundle/package identity, timestamp,platform, crash kind/signal/exception when cheaply available, process, target identity, and artifact
availability.
getshould copy/download one report into the session artifact store and return path,size, checksum when available, provenance, and a bounded summary. Raw reports must never be dumped by
default.
Platform research
Document capabilities and limitations before finalizing a cross-platform contract:
whether IDs remain stable after reboot and how app identity is filtered.
devicectl/device diagnostics availability, pairing/developer-moderequirements, permissions, OS/Xcode version gates, and whether retrieval can be app-scoped.
tombstones/ANRs; determine what is retrievable without root and what only exists as bounded log
evidence.
applications by default.
APIs expose crash reports; return typed unsupported capability otherwise.
name.
Architecture constraints
packages/contracts/src/interaction-guarantees.tsonly if this is an interaction guarantee; otherwiseuse the command descriptor/capability registries that own command support. Do not manufacture parity
through command-name lists.
src/utils/exec.tshelpers.src/daemon/session-store.tsand the existing artifact response model;do not hand-build session paths or write ad-hoc logs.
normalizeErrorfields and typed details (reason, permission/tool/version requirements,attempted source). No message sniffing.
must not leak unrelated app names or user data in default output.
referenced by path/handle.
debug symbolsremains the symbolication owner. Retrieval should compose with it ratherthan duplicate UUID matching, frame parsing, or dSYM search.
descriptor surface. Add an MCP
outputSchemafor closed result shapes.Proposed result sketches
List result:
{ "crashes": [ { "id": "provider-stable-id", "occurredAt": "2026-08-16T12:00:00Z", "app": "com.example.app", "process": "Example", "platform": "ios", "kind": "exception", "summary": "EXC_BAD_ACCESS" } ], "truncated": false, "source": "platform-diagnostics" }Get result:
{ "crash": { "id": "provider-stable-id", "occurredAt": "...", "app": "..." }, "artifact": { "artifactType": "crash-report", "path": ".../crash.ips", "sizeBytes": 12345 }, "summary": { "exception": "EXC_BAD_ACCESS", "topFrames": [] } }Treat these as design prompts, not wire compatibility commitments.
Verification plan
.ips/.crash, Android fatal exception/ANR/native samples, andmalformed or partially written reports. Shared fixtures are named exports, not repeated literals.
unsupported/permission failures.
debug symbols, including matchingand mismatched dSYM cases.
new test fail before implementation, then pass after the owning interface exists.
unrelated app.
artifact size is preserved accurately.
recovery hints.
--json, Node result types, MCP structured content/output schema, artifact listing,and docs/help remain aligned.
Acceptance criteria
debug symbols.