Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
117 changes: 26 additions & 91 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,84 +1,44 @@
# mini-code-agent-langgraph
# Transactional Agent Runtime

[![tests](https://github.com/wusuiling-if/mini-code-agent-langgraph/actions/workflows/tests.yml/badge.svg)](https://github.com/wusuiling-if/mini-code-agent-langgraph/actions/workflows/tests.yml)
[![Python 3.10–3.13](https://img.shields.io/badge/Python-3.10%E2%80%933.13-3776AB?logo=python&logoColor=white)](https://www.python.org/)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://github.com/wusuiling-if/mini-code-agent-langgraph/blob/main/LICENSE)

> A compact transactional runtime for coding agents: isolate, verify, attest, then commit.
> Keep agent changes out of your source checkout until they are verified and safe to apply.

[中文详细指南](https://github.com/wusuiling-if/mini-code-agent-langgraph/blob/main/README.zh-CN.md) · [Security policy](https://github.com/wusuiling-if/mini-code-agent-langgraph/blob/main/SECURITY.md) · [Contributing](https://github.com/wusuiling-if/mini-code-agent-langgraph/blob/main/CONTRIBUTING.md) · [Changelog](https://github.com/wusuiling-if/mini-code-agent-langgraph/blob/main/CHANGELOG.md)

`mini-code-agent-langgraph` is a small, auditable runtime centered on one mechanism: an agent works in an isolated Git transaction, produces verification-bound evidence, and cannot update the source worktree until an explicit conflict-checked commit. LangGraph is the included loop adapter, not the transaction core.
Coding agents normally edit the same checkout a developer is using. A failed run, stale test result, concurrent edit, or interrupted process can therefore leave the source in an ambiguous state. Transactional Agent Runtime gives an agent an isolated Git worktree and treats its patch as a prepare/commit transaction.

![`mca demo` fixes a calculator bug, verifies the tests, and submits the patch](https://raw.githubusercontent.com/wusuiling-if/mini-code-agent-langgraph/main/docs/assets/demo.gif)
The source checkout is not updated until the runtime has verified one exact workspace state, authenticated the prepared evidence, and rechecked the source for conflicts at commit time. LangGraph is an included loop adapter, not the transaction core.

- **Verification-bound submission:** user-configured verification—legacy `--test-command` or named `--check` entries—must pass against the current workspace fingerprint before the agent can submit.
- **Transactional execution:** `mca tx` treats an agent run as a prepare/commit protocol: the source stays untouched until verification evidence and conflict checks agree.
- **Inspectable recovery:** redacted trajectories persist each run and can resume safely after an interruption.
- **Conflict-aware Undo:** a private HMAC-authenticated journal rejects post-edit conflicts by default.
## See the transaction

## Install and try it without an API key
No API key or existing repository is required:

```bash
python -m pip install mini-code-agent-langgraph
mca demo
```

`mca demo` fixes a deterministic calculator fixture in a temporary workspace. It does not modify the clone or contact a model provider. Before using a real repository, inspect prerequisites without reading secret values:

```bash
mca doctor --cwd /path/to/repo --sandbox auto --provider auto
mca sandbox probe --sandbox auto
```

`doctor` performs static prerequisite checks. `run` and coding-enabled `chat` sessions perform the authoritative backend startup check; a coding-enabled chat is one started with `--test-command` or `--check`. An `/ask`-only chat started without either skips that check because it cannot run tests, shell commands, or coding tools. Doctor checks whether a provider key is present in the current process environment without printing its value, and inspects private env-file metadata without opening the file.

`mca sandbox probe` goes further: without a provider key or target repository, it creates disposable data and checks a workspace write plus backend-specific outside-write, Unix-socket, and network boundaries. Native backends must read an exact host sentinel and return the probe's reserved evidence code only when mutation is blocked by `EPERM`, `EACCES`, or `EROFS`; Docker must not see that sentinel and must separately report the `ST_RDONLY` mount flag for `/`. Other positive exits, launch failures, exceptions, and timeouts are failures rather than denial evidence. `bwrap` and Docker must hide the controlled and known host Unix sockets, while `sandbox-exec` may expose a path only if connection remains denied. The network check first attempts a no-packet UDP `connect` to a TEST-NET address and, only when the process cannot obtain or use an outbound route, requires denial of a controlled loopback TCP connection. It prints one `[PASS]` or `[FAIL]` result per check and rejects `--sandbox none`, which cannot demonstrate isolation. The probe itself is bounded and useful for validating a local setup, but a passing result is evidence only for these checks, not proof that arbitrary untrusted code is safe.

## Run and chat

Create a private environment-file template with `mca init`, populate it with a provider key, then use a DeepSeek or OpenAI-compatible provider for a real task:

```bash
mca init
mca run "Fix the failing tests" --cwd /path/to/repo --model deepseek --provider deepseek --test-command "python3 -m pytest -q"
mca chat --cwd /path/to/repo --model deepseek --provider deepseek --test-command "python3 -m pytest -q"
```

`mca run` is a one-shot coding run and requires both an explicit `--model` and authoritative verification configured with `--test-command` or `--check`; it rejects `--model mock`, so use `mca demo` for the deterministic no-key flow. `mca chat` is a persistent REPL that starts in read-only `/ask` mode. A chat started without either verification form remains `/ask`-only and blocks `/code`; supply one, then enter `/code`, to explicitly allow coding tools. `--yes` skips confirmations but never grants `/code` mode by itself.

For a named verification matrix, configure the checks in the order they must run:

```bash
mca run "Fix the issue" \
--model deepseek \
--check tests "pytest -q" \
--check lint "ruff check ." \
--check types "pyright"
mca tx demo
```

Named checks run serially and must all begin and end with one unchanged workspace fingerprint. A check that leaves a fingerprinted file changed invalidates the entire matrix with WorkspaceChangedDuringVerification; run generators before the matrix. Ignored cache paths retain the existing fingerprint policy.
The demo runs two deterministic transactions. The first proves that a verified patch does not touch the source before commit. The second injects a concurrent source edit and proves that commit is refused without overwriting it. Output is line-oriented and machine-readable on Linux, macOS, and Windows.

`--test-command` remains the backward-compatible single-check form. Configure at most 16 checks. Worst-case matrix time is approximately the number of checks multiplied by the per-command timeout.
## Core guarantees

Stable `--test-command` output and event fields remain compatible, but the single legacy command now also fails closed if it leaves a fingerprinted file changed. Use ignored cache paths only through the existing trusted runtime artifact policy.
- **Clean prepare:** agent tools and checks run in an isolated Git worktree; the source remains unchanged before commit.
- **Verification binding:** passing checks are bound to the exact prepared workspace fingerprint. A later change invalidates them.
- **Tamper evidence:** a local HMAC-authenticated receipt binds the baseline, patch, verification, trajectory, access log, and prepared fingerprint.
- **Conflict refusal:** commit rejects a changed source `HEAD`, any changed source-workspace fingerprint, a changed prepared workspace, or a mismatched patch.

This evidence shows that the configured commands passed under the runtime policy for one workspace state. It does not prove test completeness, code correctness, model quality, or overall system safety.
## Deliberate limits

Fingerprint capture occurs at check boundaries. It detects persisted changes but cannot prove that a command did not modify and restore a file entirely between captures; this feature does not claim immutable-snapshot execution.
- Transactions require a clean Git worktree, and private runtime state must live outside the source repository.
- Conflict detection is intentionally whole-workspace: even an unrelated concurrent source edit rejects commit rather than attempting a merge.
- Receipts are local tamper evidence, not portable signatures, proof of test completeness, or proof that a patch is correct.
- Native Windows has no built-in isolation backend. `--sandbox auto` requires Docker; `--sandbox none` is an explicit unisolated opt-out.
- The short pre-apply check is not a filesystem-wide lock against every possible external race.

Matrix configuration commands are not directly serialized into structured evidence and output is bounded. Redaction is best effort for known patterns, environment values, and values configured through the existing redaction controls; arbitrary command output can echo command text or values that cannot be classified perfectly. Treat trajectory files as sensitive and do not publish them without review.

Runs and chats save a trajectory. Inspect it or preview a conflict-aware undo before changing files:

```bash
mca trace /path/to/run.traj.json --diff
mca undo /path/to/run.traj.json --dry-run
```

## Transactional runs

Use a transaction when the agent must not edit the source worktree before its patch is verified and explicitly committed:
## Run a real transaction

```bash
mca tx run "Fix the failing tests" \
Expand All @@ -91,28 +51,13 @@ mca tx receipt TRANSACTION_ID
mca tx commit TRANSACTION_ID
```

`tx run` snapshots a clean Git root, creates a detached worktree under the private state directory, and runs the normal sandboxed agent there. Tool calls are persisted as a write-ahead access log with read/write sets. A run reaches `prepared` only when the agent submits and its passing verification fingerprint exactly matches the isolated workspace. Until `tx commit`, the source worktree is unchanged.

`tx commit` fails closed unless the source `HEAD` and entire source-workspace fingerprint still match the begin snapshot and the isolated workspace still matches the prepared fingerprint. It checks the binary Git patch before applying it; ignored or otherwise non-patchable workspace changes cannot be prepared. This first version deliberately uses whole-workspace conflict detection. The recorded read/write sets are audit evidence, not yet a promise that unrelated concurrent edits can be merged.

Every prepared transaction receives an HMAC-authenticated receipt binding the baseline, patch hash, verification evidence and fingerprint, trajectory digest, WAL digest, and access sets. `tx commit` verifies that receipt against durable state; `mca tx receipt` renders its non-source evidence. This is local tamper evidence under the private machine key, not a portable signature or proof that another machine should trust.

If the process stops after a complete tool checkpoint, resume with the same model and verification configuration:

```bash
mca tx resume TRANSACTION_ID --model deepseek --check tests "pytest -q"
mca tx abort TRANSACTION_ID
```

Transaction metadata, checkpoints, patches, and worktrees live under the private application state directory. Keep that directory outside the source repository. `commit` protects against observed pre-commit conflicts; it is not a filesystem-wide lock against another process racing the short check/apply interval.
See [the transaction protocol](docs/transaction-protocol.md) for lifecycle, receipt fields, recovery, and failure behavior. Agent-loop, provider, doctor, and sandbox operations are secondary integrations documented in [runtime operations](docs/runtime-operations.md) and [sandboxing](docs/sandboxing.md).

Run the two-path demonstration without an API key:
## Run and chat

```bash
mca tx demo
```
The package still includes one-shot `mca run`, persistent `mca chat`, DeepSeek and OpenAI-compatible providers, trace inspection, and conflict-aware undo. These are integrations around the transaction core rather than the primary product identity.

It proves that the successful source remains unchanged before commit, then injects a concurrent user edit into a second repository and shows that commit is refused without overwriting it.
See [runtime operations](docs/runtime-operations.md) for provider setup, verification matrices, chat modes, trajectory handling, and the legacy deterministic demo.

## Enforced controls and limits

Expand All @@ -121,19 +66,9 @@ It proves that the successful source remains unchanged before commit, then injec
- User-configured authoritative verification—legacy `--test-command` or named `--check` entries—must pass against the current workspace fingerprint before submission. A recognized zero-test result is rejected by default, and resume invalidates earlier verification.
- Undo uses a private, HMAC-authenticated journal and rejects post-edit conflicts unless explicitly forced.
- `--allow-zero-tests` explicitly weakens verification by allowing a recognized zero-test result to satisfy the gate. `--sandbox none`, `--allow-shell`, `--allow-dirty`, `--yes`, and force/legacy Undo options also deliberately weaken protections; `--sandbox auto` fails closed if no usable backend is found.
- Native Windows supports the Agent runtime, structured tools, `mca demo`, and transactions. Local commands use `cmd.exe`; `--sandbox auto` requires Docker because Windows has no built-in native isolation backend. `--sandbox none` is an explicit unisolated opt-out. macOS uses `sandbox-exec`; Linux uses `bwrap` or Docker when available.

Backend boundaries differ:

| Backend | Enforced boundary | Important limit |
| --- | --- | --- |
| Linux `bwrap` | Unshares namespaces and keeps the host root read-only. The workspace and executor runtime tree are the only writable host paths; private writable tmpfs mounts provide `/run`, `/tmp`, and home, alongside private `/dev` and fresh `/proc` views. | Relies on the host kernel and installed Bubblewrap; its PID namespace strengthens descendant containment but is not a guarantee against a compromised host. |
| macOS `sandbox-exec` | Denies network and default writes, hides the real home except for a workspace below it, and limits writes to the workspace plus an executor-owned private runtime tree used for `HOME` and `TMPDIR`; shared `/tmp` and `/private/tmp` are not writable. | It is an OS policy profile, not a PID namespace, cgroup, or container boundary, and Apple may deprecate or restrict it. |
| Docker | Uses no network, a read-only/capability-free container, resource limits, a single writable workspace bind, and a private size-limited `/tmp`; on POSIX it maps the invoking numeric UID:GID and explicitly sets private `HOME`/`TMPDIR`, Python-bytecode, and Git environment values. | Relies on a trusted daemon, image, host kernel, and configuration. Every coding/test image must contain `/bin/sh`; `mca sandbox probe` additionally requires `python3`. |

Native process-group cleanup after timeout, interruption, or exceptions is best effort: a double-forked process can create a new session and escape that process group. Bubblewrap's PID namespace and Docker's container boundary provide stronger descendant containment, but no backend provides an absolute OS/process-containment guarantee.
- Native Windows supports transactions and structured tools. Local commands use `cmd.exe`; process isolation requires Docker.

These controls are defense in depth, not a guarantee that an untrusted repository, command, dependency, image, host, or provider is safe. Do not run it in a workspace containing production credentials. Read the complete [security policy](https://github.com/wusuiling-if/mini-code-agent-langgraph/blob/main/SECURITY.md) before use.
Read [sandboxing](docs/sandboxing.md) for backend boundaries and probes, and the complete [security policy](https://github.com/wusuiling-if/mini-code-agent-langgraph/blob/main/SECURITY.md) for the threat model.

## Offline verified-patch benchmark

Expand Down
Loading