harness_loop_engine/lib.rs
1//! # harness-loop-engine — loop engineering for harness-rs
2//!
3//! *Agent = Model + Harness.* A **harness** wraps a single agent call. A
4//! **loop** wraps the harness: it runs that call again and again, on a
5//! cadence, with state, verification, budgets, and gates — driving toward a
6//! goal over time instead of in one shot. This crate is harness-rs's loop
7//! layer.
8//!
9//! > "Loop engineering is replacing yourself as the person who prompts the
10//! > agent. You design the system that does it instead." — and you stay the
11//! > engineer responsible for that system.
12//!
13//! The building blocks already live elsewhere in harness-rs — scheduling
14//! (`harness-scheduler`), worktrees (`harness-sandbox`), sub-agents
15//! (`harness-loop`), memory (`harness-core`), MCP (`harness-mcp`). What this
16//! crate adds is the **orchestration discipline** that turns those parts
17//! into a loop you can trust:
18//!
19//! - [`LoopLevel`] — maturity levels **L1 (report) → L2 (assisted) → L3
20//! (unattended)**. A loop earns autonomy in stages.
21//! - [`HumanGate`] — the proceed-or-escalate decision, tied to the level.
22//! Built-ins: [`AlwaysEscalate`], [`AllowlistGate`], [`CallbackGate`].
23//! - [`TokenBudget`] — a per-round spend ceiling, because unattended loops
24//! spend without bound if you let them.
25//! - [`LoopSpec`] — the inert, serializable description of a loop.
26//! - [`LoopEngine`] — the runner: recall state → isolate → **maker**
27//! sub-agent → **checker** sub-agent → gate → record state.
28//! - [`LoopScheduler`] — runs loops on their cadence.
29//! - [`patterns`] — the seven named production loops (daily triage, PR
30//! babysitter, CI sweeper, …), each a ready-made [`LoopSpec`].
31//!
32//! ## The anatomical loop
33//!
34//! ```text
35//! schedule (cadence)
36//! │
37//! ▼
38//! recall STATE / memory ──► isolated worktree (sandbox)
39//! │ │
40//! │ ▼
41//! │ maker sub-agent (proposes)
42//! │ │
43//! │ ▼
44//! │ checker sub-agent (tests + gates)
45//! │ │
46//! │ ▼
47//! │ human gate? ──┬─ safe/allowlisted ─► proceed
48//! │ └─ risky/ambiguous ──► escalate
49//! ▼ │
50//! write STATE / memory ◄────────────────────────── recurse next tick
51//! ```
52//!
53//! ## Two debts to watch
54//!
55//! Loop engineering names two failure modes that accrue silently. This
56//! crate makes them *visible* rather than solving them — they are
57//! engineering responsibilities, not features:
58//!
59//! - **Intent debt** — the drift between what a loop was *meant* to do and
60//! what it actually does. Antidote: [`LoopSpec::intent`] is a required,
61//! one-sentence statement of purpose, injected into every maker turn and
62//! printed in every report. Review it as the loop evolves.
63//! - **Comprehension debt** — the gap between what the loop ships and what
64//! humans still understand about its behaviour. Antidote: the
65//! maker/checker split, the recorded state spine, and rendered reports
66//! keep a legible trail of every round.
67//!
68//! ## Safety stance
69//!
70//! Verification stays on you — unattended loops make unattended mistakes.
71//! Defaults are conservative: L1 makers are strictly read-only, the default
72//! gate for every level is [`AlwaysEscalate`], and L3 auto-proceed requires
73//! an explicit [`AllowlistGate`]. Graduate a loop's level only as you build
74//! trust in it.
75
76mod budget;
77mod engine;
78mod level;
79pub mod patterns;
80mod scheduler;
81mod spec;
82
83pub use budget::{BudgetLimit, BudgetState, TokenBudget};
84pub use engine::{LoopEngine, RoundOutcome, RoundReport};
85pub use level::{
86 AllowlistGate, AlwaysEscalate, CallbackGate, GateDecision, HumanGate, LoopLevel,
87 ProposedAction, default_gate_for,
88};
89pub use scheduler::{LoopScheduler, LoopSink, StdoutSink};
90pub use spec::LoopSpec;