# CCD Renewal Through Lifeloop

## Scope

Use this playbook for the current greenfield CCD renewal flow through Lifeloop.
CCD owns renewal leases, the `renewal_intents` table, the `renewal-state`
continuation blob, blob validation, and thread binding. Lifeloop owns lifecycle
event dispatch and opaque continuation-blob persistence.

The historical `ccd-renewal` host-asset profile is a compatibility path for old
host-hook installs. Current CCD does not expose a CCD-owned session-renew
command; do not document or depend on that old command family for greenfield
CCD.

## Enable

Configure Lifeloop's subprocess callback path so lifecycle events are delivered
to CCD's callback consumer:

```bash
lifeloop event invoke \
  --client-cmd "${CCD_BIN:-ccd}" \
  --client-arg lifeloop \
  --client-arg client
```

`lifeloop event invoke` reads a `DispatchEnvelope` on stdin and emits a
`LifecycleReceipt`. `ccd lifeloop client` reads the callback envelope, performs
CCD-owned state transitions, and returns a `CallbackResponse`.

Host-asset installation is outside this playbook. Any host-specific bridge must
eventually deliver the same Lifeloop callback envelope to `ccd lifeloop client`.

## Renewal Sequence

1. Lifeloop dispatches a lifecycle event to `ccd lifeloop client`.
2. CCD reconciles any pending renewal intent for the resolved
   `(profile_id, channel_id)` before ordinary start/open-spin work.
3. If the operator or a manifest-supported `context.pressure_observed`
   callback needs a renewal, CCD prepares one through:

   ```bash
   ccd renewal prepare --adapter codex --reset-path wrapper
   ```

4. `ccd renewal prepare` writes one pending `renewal_intents` row and stores a
   CCD-owned `renewal-state` blob via `lifeloop continuation put`.
5. After restart, the next top-level lifecycle start reaches
   `ccd lifeloop client`. CCD reads `renewal-state` via
   `lifeloop continuation get`, validates the blob, opens or reuses the spin,
   marks the intent `fulfilled`, and runs the reconciliation sweep.
6. Corrupt, expired, missing, or mismatched `renewal-state` data fails closed
   through the typed renewal transition path; Lifeloop never invents CCD state.

## Inspect Evidence

Greenfield CCD renewal state is split across:

- CCD's profile SQLite store, which owns `renewal_intents`.
- Lifeloop's continuation store, which holds the opaque `renewal-state` blob
  under key `renewal-state` and client id `ccd`.

Use `ccd context show` for the resolved thread/spin view and
`lifeloop continuation list --thread <ccd-thread-id>` only when debugging the
opaque continuation-store slot. Do not read blob contents as Lifeloop state; CCD
owns the schema and validation.

## Fallback

If renewal prepare fails because the manifest lacks
`renewal.reset.wrapper_mediated` or
`renewal.continuation.payload_delivery`, use CCD's manual renewal path and do
not claim automatic renewal for that adapter. If the `renewal-state` blob is
lost or invalid, follow CCD's operator-required response; Lifeloop must fail
closed rather than inventing a continuation.
