Latticeflow

Latticeflow: Making AI Agents Deterministic

4 min read Updated July 23, 2026

AI coding agents are powerful and completely non-deterministic. Latticeflow wraps them in one: a single native binary that drives a ticket through a deterministic plan, implement, review, ship lifecycle - and only pays for an agent on the steps that actually need one. I use it to build almost everything else on this site.

The Problem

My earlier approach drove everything through a persistent chat session that re-read its whole prompt corpus on every action. One 7-ticket chain on TradeTrack2 took four hours and burned about 190 million cache-read tokens - call it $258 in equivalent API tokens if I hadn’t been on a Max plan. Roughly 76% of that was the chat re-reading its own 26k-token corpus on every transition. I was using a chat loop as a state machine and paying the full corpus cost on every step.

No money actually left my account, so that number isn’t a war story about spend. It’s the target: burning tokens is not the achievement, doing the same work on a fraction of them is. And when Anthropic announced they would start charging API rates for piped CLI commands, the rebuild stopped being an optimization and became preparation.

What I Built

Latticeflow, a single-binary command-line tool called build that owns the full lifecycle of a development ticket. Point it at a Plane project, give it a ticket, and it drives that ticket through a deterministic state machine: plan the work, cut a git worktree, implement the changes, run a gate of automated checks, dispatch a review, and ship the result back to the target branch. Every phase either succeeds, fails with a classified exit code, or triggers a bounded rework loop. No daemon, no server, no shared state across invocations - the binary exits at the end of each verb.

Latticeflow replaced Claude-Config, an earlier corpus of markdown slash-commands that drove ticket lifecycles through a live Claude Code chat acting as runtime, state machine, and tool gateway all at once. That corpus shipped real tickets on real projects, TradeTrack2 among them, and it’s the reference implementation behind The Shape of Done. Latticeflow is the public name, build the binary, throughline-build the repo.

Tech Stack

Languages
  • C#
Runtime & frameworks
  • .NET 10
  • native AOT (single self-contained binary)
  • System.Text.Json
Data & storage
  • TOML config
  • Plane backend (git worktrees for isolation)
Infra & deploy
  • cross-platform AOT builds (Windows / macOS / Linux)
  • GitHub Actions three-platform CI matrix
AI / ML
  • multi-vendor worker orchestration - Claude Code
  • Codex
  • Gemini
  • Copilot CLIs
  • ConPTY / Unix PTY interactive transport
Testing
  • xUnit (~2
  • 200 tests across 19 projects)

How It Works

C# on .NET 10, compiled to a native-AOT single executable that needs no .NET runtime on the target. Every interaction falls into one of three tiers: state transitions, gates, and Plane writes are plain deterministic code; small scoped decisions are single API calls; plan, implement, and review spawn a worker CLI in an isolated git worktree.

The worker layer is genuinely multi-vendor. Claude Code, Codex, Gemini, and Copilot each sit behind an IWorkerAgent implementation, selectable globally or per phase, each handling its own auth posture - so all LLM cost flows to the operator’s subscription and the orchestrator never touches provider credentials directly.

Between implement and review, a deterministic gate runs the configured checks and proves itself first: a vacuity prover hard-fails any gating check that can’t actually fail, and a control prober re-runs failed checks against the untouched base ref so a broken environment is never blamed on the ticket.

Latticeflow ticket state machine Latticeflow drives one ticket left to right through six states: plan, cut worktree, implement, gate, review, and ship. Review can send the ticket back to implement, capped at two rework rounds. The gate runs two provers of its own: GateVacuityProver proves every gating check can actually fail, and GateControlProber re-runs failed checks against the untouched base ref. Three tiers of work sit under the spine: deterministic code with no LLM covers state transitions, gates and ticket writes; single API calls cover small scoped decisions; and a worker CLI in a git worktree runs only in plan, implement and review. Any phase can end the run with one of twelve exit codes, 0 through 11, mapped by ChainExitCodeMapper. Latticeflow one ticket, plan to ship the gate proves itself GateVacuityProver proves every gating check can actually fail GateControlProber re-runs failed checks on the untouched base ref plan cut worktree implement gate review ship rework, max 2 rounds deterministic code, no LLM state transitions, gates, ticket writes single API call small scoped decisions worker CLI in a git worktree - only plan, implement, review exit codes 0..11, mapped by ChainExitCodeMapper every phase either succeeds, fails with a classified code, or reworks clean | gate vacuity | ReviewUnavailable (quota / rate-limit) | gate env failure | ticketing outage
One ticket through Latticeflow: a deterministic spine, a gate that proves itself, and only three phases that ever spawn an agent.

The chain orchestrator drives multi-ticket trees through a post-order traversal with accumulated integration branches - children ship into a parent’s local chain branch, nested parents merge up, and only the outermost chain lands and pushes. Multi-ticket dispatch builds a graph from blocked_by relations and runs level-synchronously with bounded concurrency.

What Made It Hard

Making a non-deterministic tool behave deterministically at the boundaries. Attributing cost per action across four different vendor CLIs. Proving a passing gate actually tested something. And building an interactive transport for Claude Code after Anthropic moved --print usage onto a separate credit allowance: launching Claude under a platform PTY (ConPTY on Windows, a Unix PTY elsewhere), feeding the brief as a file reference, and detecting completion by tailing the persisted transcript once the per-turn Stop hook stopped firing in interactive sessions. Validated green on Windows 11, macOS 26.4 arm64, and Ubuntu 24.04.

The Throughline

This is the tooling underneath everything: I built the system that builds the products. It’s the productized version of the method in The Shape of Done, writing to my self-hosted Plane fork, and it’s the difference between using AI and engineering with it.

Status

Active development, and dogfooded - every ticket in Latticeflow ships through Latticeflow. The four worker agents, the full plan-through-ship pipeline, the chain orchestrator with gate and batch implement, the bootstrap verbs, and the interactive Claude Code transport are all functional and in daily use, with the AOT binary built and tested across all three platforms and roughly 2,200 xUnit tests. A vendor-neutral model client with SSE streaming is built and tested but not yet wired onto a production path. Plane is the sole ticketing backend today; GitHub and Linear remain aspirational.