converge-core 0.6.0

Converge Agent OS - correctness-first, context-driven multi-agent runtime
Documentation
# Converge Core

A correctness-first, context-driven multi-agent runtime library.

**Website:** [converge.zone]https://converge.zone | **Docs:** [docs.rs]https://docs.rs/converge-core | **Crates.io:** [converge-core]https://crates.io/crates/converge-core

`converge-core` is the foundational semantic engine for the Converge workspace. It contains the pure mechanisms for convergence, context management, and abstraction traits. It is designed to be agnostic of specific domain logic or LLM provider implementations.

## Workspace Role

Converge is organized into several specialized crates:

| Crate | Responsibility |
|-------|----------------|
| **`converge-core`** | **Foundational engine, context, and traits (Pure)** |
| `converge-provider` | LLM provider implementations (Anthropic, etc.) |
| `converge-domain` | Domain-specific agents and business logic (Growth, etc.) |
| `converge-tool` | Developer tools, Gherkin validation, and contracts |
| `converge-runtime` | HTTP/gRPC server and CLI/TUI interfaces |

## Overview

Converge Core provides the foundational runtime for building systems where:
- **Context is the API** — Agents collaborate through shared data, not direct calls
- **Convergence is mandatory** — Execution proceeds until a fixed point is reached
- **Correctness over availability** — Wrong answers are worse than no answers

## Core Concepts

### Context
The shared, typed, evolving state of a job. Context is append-only in meaning and provides the only communication channel between agents. It is fully serializable for persistence and cross-crate usage.

### Agents
Capabilities that read context and emit effects. Agents never call each other directly—all communication happens through context. The `Agent` trait is defined here but implemented in `converge-domain`.

### Engine
The convergence loop that coordinates agents, merges effects, and detects when execution has reached a fixed point. It supports parallel agent execution with serial, deterministic commit.

### Convergence
Execution halts when the context reaches a stable state (no new facts are added in a cycle).

## Agent Idempotency Contract

**This is a formal rule that all agents must follow.**

> **An agent has contributed if any artifact it emitted exists in the context — regardless of whether that artifact was accepted, validated, or promoted.**

### Why This Matters

The engine has no concept of "pending", "validated", or "proposal lifecycle". It only knows:
- Which keys are dirty (changed since last cycle)
- Which agents have dependencies on those keys
- Whether `accepts()` returns true

If an agent uses hidden state (like `has_run: bool`) to track whether it ran, it **breaks convergence guarantees**. The engine cannot reason about hidden state.

### The Correct Pattern

```rust
impl Agent for MyAgent {
    fn dependencies(&self) -> &[ContextKey] {
        // MUST include both input keys AND output key (for idempotency check)
        &[ContextKey::Seeds, ContextKey::Hypotheses]  // Seeds=input, Hypotheses=output
    }

    fn accepts(&self, ctx: &Context) -> bool {
        // 1. Precondition: input exists
        if !ctx.has(ContextKey::Seeds) {
            return false;
        }

        // 2. Idempotency: check if we already contributed (CONTEXT-BASED!)
        let my_prefix = format!("{}-", self.name());
        let already_contributed = ctx.get(ContextKey::Hypotheses)
            .iter()
            .any(|f| f.id.starts_with(&my_prefix));

        !already_contributed  // Only run if we haven't contributed
    }

    fn execute(&self, _ctx: &Context) -> AgentEffect {
        // Emit fact with stable ID prefix
        AgentEffect::with_fact(Fact::new(
            ContextKey::Hypotheses,
            "myagent-result-1",  // ID starts with agent's prefix
            "derived content",
        ))
    }
}
```

### What This Includes

Artifacts that count as "contributed":
- **Facts** — Trusted data added to context
- **Proposals** — LLM suggestions (even if later rejected)
- **Diagnostics** — Error/warning messages
- **Authority requests** — Permission escalations

### Common Mistakes

| Mistake | Why It Breaks |
|---------|---------------|
| `has_run: AtomicBool` | Hidden state — engine can't see it |
| Checking only if output key exists | Another agent might have contributed |
| Not declaring output key in `dependencies()` | Agent won't be reconsidered when output changes |

### Proof Tests

Run the axiom proof tests to verify these guarantees:

```bash
cargo test -p converge-core --test engine_convergence_axioms -- --nocapture
cargo test -p converge-core --test engine_convergence_bones -- --nocapture
```

See [CONVERGENCE_PROOFS.md](./CONVERGENCE_PROOFS.md) for detailed documentation.

## Quick Start

```rust
use converge_core::{Engine, Context, ContextKey};
use converge_core::agents::{SeedAgent, ReactOnceAgent};

// Create engine and register agents
let mut engine = Engine::new();
engine.register(SeedAgent::new("seed-1", "initial data"));
engine.register(ReactOnceAgent::new("hyp-1", "derived insight"));

// Run until convergence
let result = engine.run(Context::new()).expect("should converge");

// Inspect results
assert!(result.converged);
assert!(result.context.has(ContextKey::Seeds));
println!("Converged in {} cycles", result.cycles);
```

## Public API

### Core Types

- [`Engine`] — The convergence runtime
- [`Context`] — Shared job state
- [`Agent`] — Agent trait for implementing capabilities
- [`AgentEffect`] — Buffered output from agents
- [`Fact`] — Typed facts added to context
- [`ProposedFact`] — LLM suggestions requiring validation
- [`LlmProvider`] — Abstraction for external LLM backends

### Guarantees

- **Determinism**: Same input → same output
- **Termination**: Budgets prevent infinite loops
- **Isolation**: Agents never call each other
- **Auditability**: All changes are traceable

## Documentation

For detailed API documentation, run `cargo doc -p converge-core --open`.

For high-level architecture and design principles, see the [public documentation](../docs/).

## License

MIT