Skip to main content

guides/recovery-envelope.md

# Recovery Envelope

`cli_subprocess_core` normalizes provider, runtime, transport, and protocol
failures into a shared recovery envelope before those failures move upward into
ASM or higher runtimes.

This guide describes the contract owned here.

## Why It Exists

Provider CLIs are inconsistent about failure labels:

- capacity errors may arrive as runtime failures
- auth/config/runtime claims are often flaky or mislabeled
- transport failures can masquerade as provider exits

`cli_subprocess_core` does not decide packet/job policy, but it does decide the
normalized facts that upper layers need in order to make good policy
decisions.

## Envelope Shape

The recovery envelope is attached under `metadata["recovery"]` on structured
payload errors and under `runtime_failure.recovery` on runtime-failure
metadata.

Current keys:

- `origin`
- `class`
- `retryable?`
- `repairable?`
- `resumeable?`
- `local_deterministic?`
- `remote_claim?`
- `severity`
- `phase`
- `provider_code`
- `suggested_delay_ms`
- `suggested_max_attempts`

## Current Class Vocabulary

- `cli_missing`
- `cwd_missing`
- `transport_invalid_options`
- `transport_unsupported`
- `buffer_overflow`
- `transport_disconnect`
- `transport_timeout`
- `protocol_error`
- `provider_auth_claim`
- `provider_config_claim`
- `provider_rate_limit`
- `provider_runtime_claim`
- `approval_denied`
- `guardrail_blocked`
- `user_cancelled`

`cli_subprocess_core` may expand this set over time, but it should not emit
ambiguous, provider-specific class names when a shared class already exists.

## Ownership Boundary

`cli_subprocess_core` owns:

- provider-profile parsing and normalization
- transport/protocol failure normalization
- honest lower-layer recoverability facts

`cli_subprocess_core` does not own:

- packet/job retry budgets
- repair prompting
- verifier-driven completion
- workflow-level terminal/fail-open policy

Those belong in higher runtimes such as `agent_session_manager` and
`prompt_runner_sdk`.

## Design Intent

The key design rule is:

- normalize facts here
- decide policy above

That keeps provider and transport semantics close to the runtime that actually
observed them, while letting upper layers remain provider-agnostic.