# Lifeloop

Lifeloop is a provider-neutral lifecycle abstraction and normalizer for AI
harnesses.

It exists because AI harness lifecycle is a reusable substrate. Claude Code,
Codex, Gemini, Hermes, OpenClaw, OpenCode, and future harnesses expose session,
prompt, context-pressure, turn, closeout, and recovery moments through different
hooks and telemetry conventions. Lifeloop normalizes those lifecycle moments so
clients can attach through a stable contract instead of importing CCD or
rebuilding harness adapters.

## Role

```text
             harnesses
  Claude / Codex / Gemini / Hermes / OpenClaw / OpenCode
                   |
                   v
             Lifeloop
 lifecycle events, receipts, capabilities, payload delivery
                   |
      +------------+-------------+-------------+
      |            |             |             |
     CCD          RLM        Reforge        Fixity
 continuity   recursion    memory family   constraints
```

## Boundary

Lifeloop owns lifecycle normalization:

- harness identity and adapter manifests;
- lifecycle event vocabulary;
- hook timing normalization;
- capability negotiation;
- lifecycle receipts;
- payload placement and delivery metadata;
- lifecycle-relevant telemetry;
- failure classes and retry posture.

Lifeloop does not own continuity, memory, recursive inference policy, model
selection, prompt semantics above placement metadata, tool abstraction, skills,
or a universal IDE.

## Why Rust

Lifeloop starts as an extraction from CCD, and CCD is Rust. Keeping Lifeloop in
Rust minimizes translation risk during extraction, preserves behavior around
the existing lifecycle normalizer, and gives the public event/capability/receipt
contracts strong local types. The callback protocol remains language-neutral,
so Go, Python, shell, or research clients can consume Lifeloop through JSON
envelopes without importing Rust.

## Current Shape

The crate implements the `lifeloop.v0.2` slice of the contract:

- lifecycle event vocabulary (14 events, including the `frame.*` family,
  `context.compacted`, and `receipt.gap_detected`);
- callback request and response envelopes (`CallbackRequest` /
  `CallbackResponse`) plus a `DispatchEnvelope` transport-boundary shape
  carrying request + payload envelopes through one stdio document
  (issue #22);
- adapter manifest registry with built-in manifests for Codex and
  Claude as v1 conformance targets and pre-conformance manifests for
  Hermes, OpenClaw, Gemini, and OpenCode (issue #6); shared
  conformance fixture suite under `tests/conformance/` (issue #10);
- payload envelope with `placement` / `requirement` / `outcome`
  enums, opaque-by-construction renderer (bodies are transported
  verbatim so overlapping JSON keys across payloads stay
  distinguishable, per issue #21);
- lifecycle receipt with required-but-nullable correlation fields and
  per-payload `payload_receipts` carrying payload kind and optional digest
  provenance;
- 13-class `FailureClass`, 5-class `RetryClass`, and the spec's
  failure-to-retry default mapping;
- 5-state `SupportState` (`native`, `synthesized`, `manual`,
  `partial`, `unavailable`) for adapter capability claims;
- optional renewal/reset capability claims that distinguish native,
  wrapper-mediated, manual, and unavailable reset paths from
  observation-only versus payload-delivering continuation support;
- lifecycle router stack: pre-dispatch validation + adapter resolution
  → capability/placement negotiation → callback invocation
  (in-process or subprocess over JSON stdio via `DispatchEnvelope`) →
  receipt synthesis with idempotency (issues #7 / #13 / #14 / #15);
- subprocess callback transport with deadline-bounded round trip
  (issues #8 / #22);
- host integration assets (`.claude/settings.json`,
  `.codex/config.toml`, etc.) rendered through `src/host_assets.rs`
  with CCD-compat, CCD-renewal, and Lifeloop-direct profiles (issues
  #4 / #9 / #20 / #26);
- opt-in Codex CCD renewal proof: `ccd lifeloop client` consumes Lifeloop
  callback envelopes, `ccd renewal prepare` writes CCD-owned renewal state
  through Lifeloop's continuation store, and the next top-level lifecycle
  start reconciles that state without exposing continuation tokens to
  Lifeloop;
- thread-sync publisher (`crates/thread-sync-publisher/`) as the
  first non-CCD lifecycle client, consuming Lifeloop receipts over
  the same callback contract (issue #11);
- Fixity pilot (`crates/fixity-pilot/`) as the #28 non-CCD product
  pilot, consuming `DispatchEnvelope` payloads through real
  `lifeloop event invoke` dispatch and keeping Reforge-inspired
  repeated-signal policy outside Lifeloop core.

The `lifeloop` CLI is intentionally thin — every subcommand is a
shim over the library:

```bash
lifeloop events                         # print the event vocabulary
lifeloop envelope validate request      # validate JSON read from stdin
lifeloop envelope validate response
lifeloop envelope echo request
lifeloop event invoke                   # validate -> negotiate -> callback -> receipt
                                        # accepts a DispatchEnvelope on stdin
lifeloop manifest list                  # registry-backed adapter listing
lifeloop manifest show <id>
lifeloop manifest inspect <id>@<ver>
lifeloop asset preview --host <h> --mode <m>   # render host assets
                                        # optional: --profile ccd-renewal
lifeloop telemetry snapshot --host <id>
lifeloop receipt emit                   # synthesize a receipt from a wire envelope
lifeloop receipt show
lifeloop renewal status --host <h> --client-id <id>
                                        # inspect token-safe renewal automation state
lifeloop conformance run                # walk tests/conformance/ fixtures
lifeloop --output hook-protocol host-hook
                                        # synchronous host-hook broker
lifeloop version
```

Run `lifeloop --help` for argument detail, exit-code semantics, and
the spec pointer.

## Docs

- [Product thesis](docs/product-thesis.md)
- [Release gates and v0.2/v1 roadmap](docs/release-gates.md)
- [Lifecycle contract spec (normative)](docs/specs/lifecycle-contract/body.md)
- [Harness concept boundary note](docs/harness-concept-boundary.md)
- [Renewal reset capability boundary](docs/decisions/renewal-reset-capability.md)
- [Source-file ownership decision](docs/decisions/source-files-are-user-owned.md)
- [RLM development-contract declaration](docs/rlm-development-contract.md)
- [Fixity pilot client](docs/client-pilots/fixity.md)
- [CCD renewal through Lifeloop playbook](docs/playbooks/ccd-renewal.md)
- [Wire-contract review playbook](docs/playbooks/wire-contract-review.md)
- [Schema-bump playbook](docs/playbooks/schema-bump.md)

## Verification

```bash
make verify
```

Focused mutation sweeps are available through `make mutants-all`, which writes
slice evidence under `mutants.out/all`. The mutation gate excludes only the
documented behavior-equivalent survivors in `Makefile`: subprocess deadline
polling cadence and host-asset no-op rendering branches. Treat any new missed
mutant as a test gap unless it has an explicit equivalence rationale.
