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

    needs-infoWaiting on reporter or external input

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions