# AGENTS.md
> Canonical AI policy for this repo.
## Project
Lifeloop is the provider-neutral lifecycle abstraction and normalizer for AI
harnesses. It exposes normalized lifecycle events, capability manifests,
callback envelopes, payload delivery metadata, and receipts so clients can
operate on harness lifecycle without importing CCD or reimplementing adapter
quirks.
## Scope
Lifeloop owns:
- harness identity, aliases, and adapter manifests;
- lifecycle event vocabulary;
- hook timing normalization;
- integration modes such as native hook, launcher wrapper, manual skill,
telemetry-only, and reference adapter;
- capability negotiation;
- lifecycle receipts;
- payload placement and delivery metadata;
- lifecycle-relevant telemetry such as context pressure and recent activity;
- failure classes and retry posture for lifecycle operations;
- extension dispatch as a lifecycle mechanism.
Lifeloop does not own:
- CCD continuity semantics;
- memory, recall, promotion, compaction, or governance;
- recursive inference policy;
- prompt semantics above placement metadata;
- model selection;
- tool or skill abstraction;
- a universal IDE.
For the full boundary decision on harness concepts (skills, plugins, slash
commands, agents/subagents, hooks, tools/permissions, MCP, memory/rule
files), see [`docs/harness-concept-boundary.md`](docs/harness-concept-boundary.md).
The single rule is: *Lifeloop normalizes lifecycle reach. It does not
normalize meaning.*
Recommended reading order for deep implementation work:
1. `README.md`
2. `docs/product-thesis.md`
3. `docs/harness-concept-boundary.md`
4. `docs/release-gates.md`
5. `docs/decisions/`
## Coding Standards
- Read `README.md` and `docs/product-thesis.md` before deep implementation
work.
- Keep the library contract first; the CLI is an adapter and inspection
surface.
- Prefer deterministic, machine-readable behavior and fail-closed error
handling.
- Keep client semantics out of core types. CCD, RLM, Reforge, Fixity, and
other clients attach through public contracts.
- Add dependencies conservatively. Protocol and adapter boundaries should stay
auditable.
## Architecture Rules
- Lifeloop may normalize lifecycle moments; clients decide what those moments
mean.
- Public event, capability, receipt, and callback schema changes require tests
and docs in the same change.
- Do not add CCD, RLM, Reforge, or Fixity dependencies to core Lifeloop.
- Compatibility shims are acceptable only as explicit tombstones with removal
criteria, not as hidden old implementations.
## Workflow
- Run `git status` and `git diff --minimal` before any commit.
- Stage explicit paths. Never use `git add .`.
- AI-authored commits include a `Co-Authored-By:` trailer naming the model
and harness, so AI authorship stays auditable in `git log`.
## Automation Substrate
Dev-workflow automations live in harness-neutral surfaces so Claude Code,
Codex CLI, Hermes, OpenClaw, Pi, and bare CI run the same checks. Harness
configs (`.claude/`, `.codex/`, etc.) are thin shims that delegate.
- `scripts/` — reusable shell logic.
- `Makefile` — named workflows (`make verify`, `make commit`, `make bump-schema`,
`make wire-check`, `make lockfile-check`).
- `lefthook.yml` — pre-commit / pre-push gates.
- `docs/playbooks/` — review checklists referenced by every harness wrapper.
- `.cargo/config.toml` — cargo aliases (`cargo wire-test`).
Add no logic to harness configs. Logic must be reachable from `make`, `git`,
and CI without a harness present.
## Pituitary Governance Gate
A lexical governance gate (Pituitary) audits the prose corpus for
terminology drift. It is the lexical complement to `tests/spec_alignment.rs`
(structural drift between code and the lifecycle-contract spec body) — both
must stay green for a release-ready posture.
- Config: `.pituitary/pituitary.toml` (terminology policies + indexed
source bundles: spec, docs, AGENTS.md, README.md, harness wrapper
directories).
- CI jobs: `pituitary-precheck` (push) and `pituitary-mr` (MR), both
defined in `.gitlab-ci.yml` via the `nanto/infra` template.
- Runtime profiles: the config selects the `fixture` embedder for CI
speed and determinism. Switch the `[runtime.embedder]` block to a
`local-lm-studio`-style profile (see Pituitary's docs) for release
prep when real semantic checks are wanted.
- Reading output: `pituitary-precheck` fast-fails on policy load and
index errors; `pituitary-mr` reports per-finding terminology
violations with `severity` (`error` blocks once fail-closed,
`warning` is advisory) and `classification`
(`historical_alias` / `forbidden_current` / `deprecated_term`).
Local equivalent: `pituitary index --rebuild && pituitary check-terminology`.
## Testing
- Run the smallest check that proves the change.
- Prefer `cargo test --all-targets --all-features` for repo-wide validation.
- For public contracts, add serialization tests that pin wire names.
### Two contract test surfaces
These look similar; they are not. Touching one usually means touching the
other.
- `tests/wire_contract.rs` — pins the **current** JSON shape. Catches
accidental wire drift on already-shipped types. Failures here mean
*somebody changed the wire without updating the assertion or bumping
the schema*.
- `tests/spec_alignment.rs` — pins the implementation against the
**target** vocabulary in `docs/specs/lifecycle-contract/body.md`. Catches
drift between the spec and the code as the contract evolves. Failures
here are a migration checklist: each failing assertion names the
spec section it disagrees with. Acceptable to mark individual
assertions `#[ignore]` only when they are expected to fail and have a
corresponding tombstone or owning issue named in the comment (e.g.
the `AdapterManifest` shape is owned by issue #6).
When a wire-affecting change lands, update *both* tests in the same
commit: `wire_contract.rs` to reflect the new on-the-wire shape, and
`spec_alignment.rs` to confirm the new shape still matches the spec
target. If they disagree, the spec is the goal — file a tombstone and
move toward the spec, do not weaken `spec_alignment.rs` to accept
drift.
### Foreign manifest fixtures
Raw foreign plugin manifest fixtures, when needed, live under
`tests/fixtures/foreign_manifests/`. They must be synthetic,
host-neutral, client-neutral, and explicitly marked with
`provenance.kind = "synthetic"`; `tests/foreign_manifest_boundary.rs`
enforces this. Do not commit copied production manifests from external
projects or harnesses.
## Source Files
Lifeloop does not write to model instruction source files
(`AGENTS.md`, `CLAUDE.md`, `GEMINI.md`, `HERMES.md`, `OPENCLAW.md`) and
does not render replacement bodies for managed sections inside them. See
[`docs/decisions/source-files-are-user-owned.md`](docs/decisions/source-files-are-user-owned.md).
Host integration assets (`.claude/settings.json`, `.codex/config.toml`,
`.codex/hooks.json`) remain in scope and live in
[`src/host_assets.rs`](src/host_assets.rs).
## Safety
- No secrets in tracked files, docs, fixtures, receipts, or diagnostics.
- Do not overwrite user changes or reset the worktree without explicit
approval.