Skip to content

Add bounded crash discovery and retrieval as first-class debug evidence #1778

Description

@thymikee

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions