Files
grok-bot c5d495f830 refactor: modularize for coding agents (runtime, agents, boundaries)
Extract clm.runtime and clm.agents; keep session core vendor-free; inject
describe_live_event into the outer loop; enforce import boundaries and
mirror unit tests by package.
2026-08-06 17:27:17 +02:00

9.4 KiB
Raw Permalink Blame History

CLM — Context Lifecycle Management

Automated Context Lifecycle Management for LLM Agents.

Phase 4 (0.4.0a1): Production hardening (structured JSON logging, manifest schema_version, memory backup/restore, cost model per provider), A/B memory experiments (clm experiment ab-memory), multi-agent handoffs (agent_id, shared memory_namespace), and DecisionPolicy plugins. Builds on P3 calibrate/export/signal/HITL and P2 verified compaction — defaults still work offline.

CLM Kontext-System — Outer Control Loop, Orchestration Layer und Context Management Core

Systemübersicht: Outer Loop (Decision Engine), Orchestrierung (Phasen/Handoffs) und Context Management Core (Memory + Verified Compaction). Details: docs/architecture.md.

Neu hier? → Getting Started (DE) — offline in ~15–25 Min von Install bis CONTINUE / COMPACT / HANDOFF (ausführlich).

Requirements

  • Python ≥ 3.12
  • uv empfohlen

Install

uv venv && source .venv/bin/activate
uv pip install -e ".[dev]"
# optional Mem0 backend:
# uv pip install -e ".[dev,mem0]"

Optional: mise

Wenn mise installiert ist, pinned mise.toml Python 3.12 und uv (Dependencies bleiben bei uv / uv.lock):

mise install          # tools laut mise.toml
mise run install      # .venv + editable install
mise run check        # ruff + mypy + pytest

CLI Quickstart

# Create .clm/ layout (memory, sessions, manifests)
clm init --path .clm

# Dry-run DecisionEngine (coding profile defaults: soft=250k, hard=350k)
clm decide --tokens 260000 --profile coding
# → action=compact trigger=soft_compact
clm decide --tokens 360000 --profile coding
# → action=handoff trigger=hard_handoff

# Run outer loop with SimulatedAgent + fixture script (default --agent simulated)
clm run --goal "demo" --script tests/fixtures/sample_transcript.json \
  --profile coding --soft-compact 1000 --hard-handoff 50000 --max-steps 20

# Pluggable coding agent (first live adapter: Grok Build headless)
# clm run --agent grok-build --goal "…" --cwd . --profile coding --yolo --path .clm
# Docs: docs/coding-agents.md

# Resume a stopped (non-terminal) session from state.json
clm run --resume <session-id> --script tests/fixtures/sample_transcript.json --path .clm

# Inspect last metrics / decisions
clm status --session-id <id>

# Manual compact / handoff on persisted sessions/<id>/state.json
clm compact --session-id <id>
clm handoff --session-id <id>

# P3: recommend soft/hard from past metrics.jsonl
clm calibrate --profile coding --path .clm --write

# P3: export observability artifacts
clm export metrics --format json --session-id <id> --path .clm
clm export metrics --format html --session-id <id> --path .clm

# P3: external phase boundary → next decide/run prefers handoff
clm signal --phase-done --session-id <id> --path .clm

# P3: HITL — require confirm on handoff (auto-approve with --yes)
clm run --goal "…" --script tests/fixtures/sample_transcript.json \
  --require-confirm handoff --yes --path .clm

# P4: backup file memory
clm backup memory --path .clm --label pre-deploy

# P4: A/B memory backends on the same Simulated script (offline mem0 via in-memory client)
clm experiment ab-memory --goal "ab" --script tests/fixtures/sample_transcript.json \
  --backends file,mem0,hybrid --soft-compact 1000 --hard-handoff 500000 --path .clm

# P4: multi-agent identity + shared memory namespace
clm run --goal "coord" --script tests/fixtures/sample_transcript.json \
  --agent-id worker-a --memory-namespace team/shared --path .clm

clm run writes under .clm/sessions/<id>/:

  • metrics.jsonl, decisions.jsonl (decisions include step_index, total_tokens, ts; optional cost fields)
  • state.json (enables compact / handoff / --resume / signal)

Handoff manifests land in .clm/manifests/ (schema_version=1.1, optional agent_id). Exports under .clm/exports/<id>/. Backups under .clm/backups/.

P2–P4 highlights

Feature Notes
Verified Compaction After soft compact, recall score on goal/verified/constraints/blockers; fail → trigger=verify_fail handoff
Resume clm run --resume <id> --script … continues SimulatedAgent at step_index
Memory backends --memory-backend file|mem0|hybrid (file default; mem0 needs API key + optional extra)
Pluggable coding agents --agent simulated|grok-build via factory/registry; see docs/coding-agents.md
Real agent PoC OpenAICompatibleAgent (library; stdlib HTTP + injectable transport for tests)
Calibrate Peak-percentile + decision-token blend → recommended soft/hard; --write → .clm/calibrations/
Export clm export metrics --format csv|json|html
Phase signal clm signal --phase-done sets status=phase_boundary
HITL ClmConfig.require_confirm_on / --require-confirm; denied → continue + exit 2 without --yes
Cost model --provider / --price-per-1k-* or price_table; metrics log *_cost_usd
Memory backup clm backup memory / clm backup restore --archive …
A/B Memory clm experiment ab-memory → completion, tokens, recall, interventions report
Multi-Agent --agent-id, --memory-namespace (key prefix); manifest carries both conventions
Policy plugins DecisionEngine(config, policies=[BlockersForceHandoffPolicy()])
clm --help

OpenAI-compatible adapter (library)

from clm.agents.openai_compatible import OpenAICompatibleAgent

agent = OpenAICompatibleAgent(
    api_key="sk-…",
    model="gpt-4o-mini",
    base_url="https://api.openai.com/v1",  # or any compatible endpoint
)
# Wire into WorkingSession + OuterControlLoop like SimulatedAgent

Demo scenarios (Phase-1 quality gate)

Use the bundled SimulatedAgent script tests/fixtures/sample_transcript.json (4 steps; cumulative tokens.total ends around ~245k). Thresholds below are chosen so each scenario is deterministic for this fixture.

clm init --path .clm

A — CONTINUE only (high soft / hard)

Tokens stay below both thresholds → every decision is continue, no compact, task completes.

clm run --goal "demo-A continue only" \
  --script tests/fixtures/sample_transcript.json \
  --profile coding \
  --soft-compact 500000 --hard-handoff 600000 \
  --max-steps 20 --session-id demo-a --path .clm

Expected:

  • stopped_reason=completed, compact_count=0
  • decisions.jsonl: only "action": "continue"
# spot-check
grep '"action"' .clm/sessions/demo-a/decisions.jsonl
clm status --session-id demo-a --path .clm

B — Forced COMPACT (low soft)

Soft threshold crossed after the first step → one or more compact actions; window shrinks; compact snapshots land in file memory.

clm run --goal "demo-B forced compact" \
  --script tests/fixtures/sample_transcript.json \
  --profile coding \
  --soft-compact 1000 --hard-handoff 500000 \
  --max-steps 20 --session-id demo-b --path .clm

Expected:

  • stopped_reason=completed, compact_count ≥ 1
  • decisions.jsonl contains "action": "compact" / trigger=soft_compact
  • Memory keys under sessions/.../compact-* (via FileMemoryStore)
grep compact .clm/sessions/demo-b/decisions.jsonl
ls .clm/memory/logs/ 2>/dev/null || true
clm status --session-id demo-b --path .clm

C — Forced HANDOFF + manifest validation

Hard threshold crossed mid-run → handoff, schema-valid manifest written, session seeded from manifest (not full transcript).

clm run --goal "demo-C forced handoff" \
  --script tests/fixtures/sample_transcript.json \
  --profile coding \
  --soft-compact 5000 --hard-handoff 20000 \
  --max-steps 20 --session-id demo-c --path .clm

Expected:

  • stopped_reason=handoff, handoff_manifest=.clm/manifests/<ts>_demo-c.json
  • Manifest passes Pydantic HandoffManifest validation (enforced before write in HandoffPipeline) and matches schemas/handoff_manifest.schema.json (same fields as docs/manifest-schema.md)
# list + inspect
ls .clm/manifests/
# validate with project model (strict, same check as pipeline)
python - <<'PY'
from pathlib import Path
import json
from clm.models.manifest import HandoffManifest

paths = sorted(Path(".clm/manifests").glob("*_demo-c.json"))
assert paths, "no demo-c manifest"
m = HandoffManifest.model_validate_json(paths[-1].read_text(encoding="utf-8"))
print("valid:", m.goal, "tokens=", m.token_snapshot, "next=", m.next_safe_action)
PY

clm status --session-id demo-c --path .clm

Phase-1 exit checklist

Criterion Status
Outer loop steers SimulatedAgent (A/B/C) yes — integration tests + demos above
File memory write / read / search yes — FileMemoryStore
Manifest schema-valid on every handoff yes — HandoffManifest.model_validate before write
CLI: init, run, decide, compact, handoff, status yes
Audit: metrics.jsonl + decisions.jsonl yes under sessions/<id>/
No external LLM / memory service yes
Docs current this README + docs/ + plan

Plan: docs/superpowers/plans/2026-08-04-clm-mvp.md

Tests

pytest --cov=clm --cov-report=term-missing
ruff check src tests
mypy src/clm

Version

0.1.0a1 (MVP alpha)