Skip to content
justyn-clarkPublic

About

Contract-first CLI for bounded execution loops, built as the runtime companion to SMALL Protocol.

Resources

Stars

1 star

Watchers

0 watching

Forks

Repository files navigation

loopexec

CI Latest tag License: MIT Go version

Overview

LoopExec is a deterministic runtime for bounded agentic execution loops. Work progresses through an external check and stops on a computed reason — never because an agent says it is done.

Supply a work command and an external check. LoopExec bounds execution, detects regression, no progress and oscillation, applies integrity guards, and records replayable receipts. Opt-in workflows add usage evidence, scoped model-call budgets and candidate restoration. Isolation orchestration composes with operator-provided container, egress and credential hooks.

The runtime governs execution; adapters supply models, checks and infrastructure. Synthetic creative examples prove runtime mechanics, not production model quality. Observed spending cannot enforce a provider-side cap, a signature file requires explicit verification, and retaining a candidate does not establish owner acceptance.

Getting Started begins with an offline deterministic proof. SMALL describes plans, constraints, progress and handoff; LoopExec drives one bounded loop. SMALL is optional for consumers.

The normative contract is SPEC.md. The current source implements bounded execution, determinism probing, integrity and regression guards, offline-verifiable receipts, and opt-in unattended workflows. See SPEC.md section 11 for the implemented scope and remaining sub-parts.

Current status

Source identity: v0.5.0-rc.1, a release candidate adding visible model profiles and task/role assignments. See candidate notes; the Releases page establishes publication status. Workflow thresholds remain supplied by each integration.

Implemented capabilities

Implemented through v0.4.0:

  • Real bounded run loop: iterates --exec then --check until the check passes (success_condition_met), a bound trips (max_iterations_reached), or work fails (execution_failure); "no check, no loop"; computed halt reasons mapped to a stable exit-code class; typed JSONL receipts (.loopexec/run-<id>.jsonl) and atomic durable state.

  • probe-check - determinism as a 95% confidence bound (rule of three); doctor - precondition gate (determinism + isolation preflight).

  • Set-based progress + no-regression ratchet (oscillation / no-progress / regression halts) + explain-halt (raise-the-limit vs do-not-retry).

  • Metric-integrity gate (run --integrity-cmd): guards dominate success (collected-set monotonicity).

  • Receipt pinning (model tuple + sampling + context manifest + cost + check fingerprint); replay (verify a receipt offline, agent-free) and attest (HMAC-sign + verify).

  • reexecute (live re-run distribution), escalate / watch (heartbeat + structured packet), comprehension ack gate.

  • build-context - budgeted, workdir-confined, symlink-safe relevant-file slice.

  • Shared subprocess deadlines/cancellation with bounded diagnostics; fail-closed collectors.

  • run --workflow: exact usage/reservations, explicit strict/observed/unknown money, numeric progress/patience, and manifest-based best-candidate restoration.

  • An offline Go creative-workflow adapter with independent simulated roles and candidate-bound signed reviews. No Python loop, model key, network, or engine required.

  • Opt-in shared model-call budgets across run IDs, with pinned per-phase allowances and durable pre-call reservations. See the offline adapter proof.

  • isolate - two-zone orchestration: detached-clone sandbox + per-run minted/revoked credential + rendered/launched exec/agent zones.

  • Global --json output, explicit exit-code contract, contract and unit tests, GitHub Actions CI (gofmt, go vet, go test ./...).

Integration boundaries and planned sub-parts

See SPEC.md section 11:

  • The operator-provided infra isolate composes with: the container engine, the auditing egress proxy, and the provider key API (--runtime / --egress-proxy / --mint-cmd + --revoke-cmd).
  • Provider-specific live usage wrappers; the deeper metric-integrity layers (assertion-count / coverage-floor); probe-check adversarial perturbation + the in-loop sequential monitor.
  • The import_closure / dep_graph context-relevance tiers; github/slack escalation channels; the kill-the-PID watchdog actuator.
  • Full SMALL-driven task_list loop execution; container, Nix, or remote substrates and multi-worker orchestration.

Install

go install github.com/justyn-clark/loopexec/cmd/loopexec@latest

Requires Go 1.26 or newer. For the published v0.4.1 install, use @v0.4.1. That release does not contain model assignments. After RC publication, pin @v0.5.0-rc.1 to test this feature; @latest stays on stable. Prebuilt archives and SHA256 checksums are linked from GitHub Releases.

loopexec --version prints the installed version; loopexec version --json emits its machine-readable identity. See the release notes for compatibility and platform limits.

SMALL is optional for LoopExec consumers. This repository uses the tracked .small/ files for its own development audit; CI requires a canonical progress update with source or documentation changes and validates the tracked state. The SMALL integration guide covers SMALL CLI v1.1.2 with legacy v1 artifacts and opt-in collaborative v2 sessions; LoopExec remains the loop governor.

60-second proof

Run the built-in deterministic demo with no model, API key, Python runner, or network access:

loopexec demo

The command creates a red local fixture, sends it through the real bounded loop, repairs it, observes the external check turn green, writes a typed JSONL receipt, and verifies the recorded check fingerprint through the same verifier used by loopexec replay. It proves the execution/check/receipt/replay contract, not agent intelligence. For your own work command and check, follow Getting Started.

The receipt path in the output identifies the retained temporary workdir. To keep the proof at a known path, pass a fresh directory with --workdir <dir>; demo refuses to overwrite an existing .loopexec directory or status.txt fixture.

Build

From the repo root:

go build ./cmd/loopexec

Test

go test ./...

CI enforces:

  • gofmt
  • go vet ./...
  • go test ./...

Code/tooling changes also require canonical documentation and changelog updates. The generated CLI and JSON contract is checked against the runtime. Every release packages source-bound docs and publication requires matching deployed content. See continuity policy for enforced source-bound release gates and the operator/account boundary.

CLI

The implemented CLI returns deterministic human or JSON output.

Commands

  • loopexec init / demo / run / status / check / step
  • loopexec probe-check / doctor / explain-halt
  • loopexec replay / attest / report / reexecute
  • loopexec escalate / watch / ack
  • loopexec build-context / isolate / inspect-cost
  • loopexec budget status / budget reserve for cross-run child-call limits

See docs/cli.md for flags and exit semantics. The opt-in scoped budget reserves a child model call before an adapter launches it; changing the run ID does not reset the allowance. It counts calls, not tokens or dollars.

See acceptance and evidence for general-purpose objective, retention, convergence and owner-decision boundaries. The creative verification guide is an optional example. The status and roadmap distinguishes published capabilities, source changes, and remaining work.

Global flag

  • --json - emit exactly one JSON object to stdout

Example

loopexec init
# A real bounded loop: run the work command, then the check, until green or a bound trips.
loopexec run --json --check "go test ./..." --exec "make fix" --max-iterations 10
loopexec status --run-id local --iteration 1
loopexec check

Example JSON response (a converged run):

{
  "tool": "loopexec",
  "version": "0.4.1",
  "status": "halted",
  "run_id": "local",
  "iteration": 3,
  "halt_reason": "success_condition_met",
  "check_exit": 0,
  "receipt": ".loopexec/run-local.jsonl",
  "errors": []
}

Exit codes

The halt_reason string is the stable contract; the exit code is its coarse class (SPEC section 5). Every class 13-19 emits today alongside the base 0/10/12/20/30/40/50 (class 18, budget_exceeded / cost_anomaly, via inspect-cost and workflow runs; class 15, check_inadequate, via the doctor --mutate-cmd adequacy canary); only class 11's task-list reasons (no_actionable_tasks / human_required) remain reserved, and those belong to the task_list loop topology. A few individual reasons inside active classes, the doctor coverage-delta and hermeticity tiers, are still Planned (see SPEC section 11).

  • 0 success (loop ran, no halt)
  • 10 converged: success_condition_met
  • 11 terminal-blocked: no_actionable_tasks, human_required
  • 12 iteration-cap: max_iterations_reached
  • 13 integrity: blocked_path_modified, reward_hacking_detected, metric_integrity_violation
  • 14 oracle-untrusted: check_flaky, check_not_hermetic, hermeticity_violation
  • 15 check-inadequate: check_inadequate
  • 16 resumable-judgment: escalation_pending, reviewer_rejected
  • 17 no-convergence: no_progress_detected, oscillation_detected, infeasible_suspected
  • 18 budget: budget_exceeded, cost_anomaly
  • 19 liveness/drift: heartbeat_stale, model_drift_detected, comprehension_debt_exceeded
  • 20 invariant failed
  • 30 workspace invalid or missing
  • 40 execution failure
  • 50 internal error

Repository layout

SPEC.md                   canonical, normative contract (source of truth)
cmd/loopexec/             loopexec CLI
docs/architecture.md      implemented runtime architecture
docs/cli.md               current loopexec command contract
docs/integrations.md      integration guidance for the implemented CLI
docs/loop-contract.md     task_list mode profile of SPEC.md
.github/workflows/ci.yml  fmt/vet/test CI gate
scripts/feeltest.sh       deterministic shell feel test helper

SMALL relationship

This repo is SMALL-governed at the repository level. The implemented loopexec binary runs the check_fixpoint loop standalone; the full SMALL-driven task_list loop is the profile described in docs/loop-contract.md.

Read the docs in this order:

  1. SPEC.md - the canonical, normative contract (source of truth for the binary and the docs site)
  2. docs/cli.md - what the current CLI actually does
  3. docs/integrations.md - how to integrate with the current implementation
  4. docs/architecture.md - implemented architecture and integration boundaries
  5. docs/loop-contract.md - the task_list mode profile

Links

License

MIT. See LICENSE.

Offline creative workflow

mkdir -p build
go build -o build/loopexec ./cmd/loopexec
go build -o build/creative-workflow ./examples/creative-workflow
./scripts/creative-proof.sh ./build/loopexec ./build/creative-workflow build/creative-proof

The proof asserts convergence, budget stop before further work, regression restoration, stale-evidence rejection, critic skip after technical failure, and a four-attempt cap. Expected convergence is loopexec exit 10 (external check exit 0). All fixture scores, captures, and charges are synthetic; they prove runtime wiring. Read the workflow contract for interfaces, receipts, trust boundaries, and live setup. Migration: a nonzero --budget-usd now requires explicit workflow metering; legacy set-based progress remains the default.

About

Contract-first CLI for bounded execution loops, built as the runtime companion to SMALL Protocol.

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages