Skip to content

Latch v0.2.2

Choose a tag to compare

@JinShuo-Li JinShuo-Li released this 25 Sep 11:58
· 342 commits to main since this release

Latch v0.2.2 makes the agent scriptable, coordinated, and harder to fool. It
adds a stable machine interface (latch run, resume, sessions, doctor)
for scripts, CI, and benchmark harnesses, durable agent groups for parallel
workstreams, and a deterministic release gate that CI runs on every change.
Security and evidence got stricter: sandboxed processes and native tools cannot
reach Latch credentials or its state directory, an approval can never grant
something the sandbox cannot execute, and only kernel validation can call a
changed workspace verified.

Highlights

A stable machine interface

  • latch run, latch resume, latch sessions, and latch doctor are the
    non-interactive surface for scripts, CI, coding agents, and benchmark
    harnesses. They never open the TUI, never wait for a human, and never mix
    diagnostics into stdout. latch still starts the TUI, and latch -p "..."
    (also with --resume) now runs through the same machine implementation.
  • Prompt sources are exclusive: exactly one of --prompt, --prompt-file, or
    --stdin. --workspace resolves and canonicalizes before session selection,
    policy, prompt compilation, and tools.
  • --output text (the default) preserves the historical one-shot behavior and
    streams assistant text. --output json prints exactly one versioned object
    ("schema_version": 3) with command, session, workspace, run status, resolved
    provider/model/effort, durable task state, scoped usage, context accounting,
    and event/graph summaries. --output jsonl streams semantic records
    (text_delta, tool_result, durable_event, final).
  • Usage is scoped to the invocation (usage.scope = "invocation_graph"): a
    resumed run counts only ModelUsage events emitted after it began, existing
    children exclude prior history, and children spawned mid-invocation count from
    their own beginning. Provider categories that were never reported stay null
    instead of being fabricated as zero.
  • Run status stays distinct from durable completion. status=completed means
    the invocation ended normally; use task.completion, task.evidence_count,
    and task.validation for the kernel's durable state.
  • Exit codes are stable: 0 completed, 1 runtime failure, 2 CLI/config error,
    3 permission unresolved, 4 cancelled. SIGINT or SIGTERM cancels a run and
    still emits the final structured result with status=cancelled.
  • Machine mode is fail-closed for permissions: an Ask the policy cannot
    resolve without a human is durably denied and exits 3. There is no --yes or
    skip-permissions flag, and existing invocations keep working.

Preflight doctor

  • latch doctor checks the machine a run depends on: the mandatory Bubblewrap
    sandbox (probed with a minimal sandboxed command), the rg search runtime,
    Git, the effective config path and state directory, the resolved
    provider/model/effort, and that the provider credential resolves.
  • It never contacts the provider, never runs a task, and never prints secret
    material: a credential is reported only by its symbolic reference
    (env:NAME, file:NAME).
  • Human-readable by default, one versioned JSON object with --output json.
    Exit 0 when every required check passes, 1 for a runtime prerequisite, and 2
    for a CLI or configuration error.

Agent groups

  • Agent groups add durable coordination on top of child agents: a shared task
    DAG with validated dependencies, atomic compare-and-set claims with exactly
    one winner, a durable peer mailbox delivered exactly once at safe model
    boundaries, and replayable progress state. Groups never own workers, are
    created lazily on first use, and ordinary single-agent and subagent use is
    unchanged.
  • Three fixed tools expose coordination: group_task, group_message, and
    group_status. spawn_agent { task_id } joins a child and assigns a ready
    task atomically; only its assignee can start, complete, block, or release it,
    and only the root can cancel or reassign.
  • Root terminal complete is refused while required group tasks are still
    pending, claimed, in progress, or blocked. An interrupted child keeps its task
    until an explicit release, reassignment, or completion, so a crash cannot
    duplicate work. Completing a task is coordination truth, never root evidence.
  • Messages are information-only and never wake an idle child or copy
    transcripts. Workspace conflicts are advisory warnings from declared paths,
    never hard blocks; depth stays 1.
  • The sidebar shows a compact GROUP block with task counts and active owners,
    and /group prints the full coordination view.

Cross-session cache locality

  • The provider system field and tool schemas are now session-independent:
    workspace, repository instructions, and mode moved into the first
    provider-visible message as an explicitly delimited kernel block, so the
    cacheable prefix is reused across sessions and mode switches. The session
    block stays distinct from the user request, and Anthropic merges adjacent
    user roles into ordered, separate text blocks instead of one concatenated
    string.
  • Measured against OpenCode Go with two fixtures differing only by AGENTS.md:
    the second session's first request read 4096 tokens (88.7%) from the provider
    cache (was 0), and aggregate cache_read/input rose from 0.769 to 0.922.
  • Prompt fragments are ordered least-volatile first, with mode as the trailing
    fragment, and the system prompt was trimmed ~12.8% (1489 -> 1298 estimated
    tokens) plus tightened tool schemas without changing any tool name, parameter,
    enum, or semantic. Read-only inspection, narration, and validation discipline
    are now explicit instructions.
  • Bounded recall selects the newest matching rows first and presents them
    chronologically, so a later correction survives /compact and resume even
    when older turns repeat the term.

Security and truthful completion

  • Credentials are isolated from sandboxed processes: the resolved state
    directory and symlinked secret targets are masked for shell and extension
    processes, and the kernel-native read_file/read_image/search/write/
    patch tools refuse the state directory and symlink aliases into it.
  • Approval can no longer grant what the sandbox cannot execute: unknown tools,
    external write targets that cannot be mounted, and Latch state or credential
    targets are refused before a normal approval prompt, and a grant cannot
    override those refusals.
  • Whole-file writes require strict compare-and-swap: base_hash must match the
    current bytes exactly, so one agent can no longer silently overwrite another
    agent's newer write. The stale error names the path and both hashes, and the
    agent can re-read and retry.
  • Read-only Git queries are classified per invocation, so git config --get,
    git status, and .git-excluding path filters no longer trigger spurious
    metadata-write approvals in machine mode. .git stays read-only in the
    sandbox, so this only narrows the Ask heuristic.
  • Passing validation certifies only its durable workspace generation: guarded
    edits and write-capable shell commands advance the generation, a running
    write-capable managed process blocks certification until it exits and
    revalidates, and resume rebuilds the same state without deleting history.
  • Verification is separate from loop termination: only Verified ends a run on
    the strength of its own claim. A run that actually mutated the workspace and
    is about to finish ImplementedNotVerified gets exactly one corrective turn
    to validate or record why verification is unavailable, and no correction can
    ever promote a run to Verified.
  • Tool failures stay typed across providers: is_error survives the durable
    projection, Anthropic uses native tool_result.is_error, and the
    Chat Completions and Responses adapters use a small
    [latch:tool:ok]/[latch:tool:error] envelope instead of inventing an
    unsupported field.
  • read_file/read_artifact are bounded (64 KiB per call, paged line windows,
    explicit continuation markers), search pages with a total count, and binary
    or invalid UTF-8 input is rejected honestly.

Reliability

  • Every extension lifecycle stage is bounded end to end by the central
    [extension_lifecycle] policy: spawn/initialize, ready, ordinary RPCs,
    shutdown, and graceful exit. A missed deadline kills and reaps the child, and
    startup observes cancellation, so a silent extension cannot block Latch.
  • The sidebar derives the latest durable user request from kernel events, so
    live and resumed sessions show the same request state.
  • OpenCode Go's default endpoint now targets the versioned gateway
    (https://opencode.ai/zen/go/v1), fixing HTTP 404s; endpoint detection, the
    stable x-opencode-session header, and model selection are unchanged.

Architecture and CI

  • docs/RUNTIME_CAPABILITY_MODEL.md defines the kernel invariants extensions,
    backends, and clients may not bypass, the replaceable-port rules, and the
    implemented-vs-deferred port map. A narrow ContextEngine port replaces the
    direct continuity dependency (request/result objects, no EventStore or
    SQLite in the contract), propagates to children through one factory, and
    fails closed rather than silently falling back. Default behavior stays
    byte-identical.
  • bash scripts/release-gate.sh is the deterministic release gate: a Bubblewrap
    namespace/mount probe, formatting, locked Clippy with -D warnings, the
    kernel invariant tier, the full workspace suite, and a locked release build.
    CI runs the same gate on an ephemeral Ubuntu 24.04 runner with Bubblewrap and
    user namespaces enabled.
  • The optional Docker dogfood harness runs the machine CLI against a disposable
    workspace in a non-root container without host networking or baked
    credentials, records image/source provenance, and includes deterministic,
    credential-free integration checks.

Install

Download latch-v0.2.2-x86_64-unknown-linux-gnu.tar.gz below and verify it
with SHA256SUMS, or install from the repository:

cargo install --path crates/latch-cli --locked

The archive contains the stripped latch binary, LICENSE, README.md,
config.example.toml, and BUILD_INFO (source commit, toolchain, and sandbox
versions). Runtime prerequisites are bwrap (mandatory sandbox) and rg
(search); run latch doctor to check them before your first task.

Validation

  • bash scripts/release-gate.sh passes on the release commit: formatting,
    Clippy with -D warnings, the kernel invariant tier, the full workspace test
    suite (kernel, providers, sandbox/command, continuity, CLI machine interface
    against a loopback SSE mock provider, extensions, snapshots, dogfood, group,
    and stagnation suites), and a locked release build.
  • CI is green on the same commit on Ubuntu 24.04 with Bubblewrap namespaces and
    the mandatory sandbox probe (run 36110454628).
  • Live, paid-provider tests remain opt-in and ignored, and are not counted as
    deterministic CI. Real-provider dogfood measurements made during development
    (cross-session cache reuse, prompt trimming, Git classification) are recorded
    in docs/DOGFOOD_EXPERIMENTS.md, and the long-horizon report in
    docs/LONG_HORIZON_TEST_REPORT.md documents 161/189-model-turn runs with
    rollover and resume.

Full Changelog: v0.2.1...v0.2.2