Agents · August 3, 2026

State in Git, not in context

Arkaint is the project I wrote a postmortem about. It never got users, but the architecture underneath was real, and worth writing down before it fades from memory too.

The shape of it

Three commands, one script (scripts/arkaint-loop.sh), state living entirely in Git plus a gitignored .arkaint/ scratch directory.

operator
   │
   ├── checkpoint              validate + commit current state
   ├── boot "task" [profile]   single Goose launch
   └── cycle ["task"] [profile]  checkpoint → launch → self-correct

Entry gate

Before anything runs, every command passes two checks: a branch-isolation lock (must be on arkaint/* or ephemeral-*) and profile validation (strategist | auditor | reviewer | debugger | default). Bad input gets rejected before any side effect: no tests run, nothing gets committed.

checkpoint: the commit primitive

Run tests, git add -A, and if anything staged, a structured commit. The commit message is always [arkaint-sync] checkpoint; the body carries structured metadata: state hash, token load, branch, provider, model, status (stable), UTC timestamp, task, message.

Tests run under set -euo pipefail before the commit, so a failing test aborts the whole run: a checkpoint is never a broken state. verify-spec.sh runs here too, as a gate checking spec/code alignment before the commit lands.

boot: build context, launch once

Every boot assembles a three-layer boot packet:

Layer 1  Intent      last 3 [arkaint-sync] commits
Layer 2  Topology    git diff --stat across those 3
Layer 3  Micro-diff  git diff -U2, char-capped per profile, sensitive paths excluded

Plus an optional profile preload (glob-matched reference files), capped into boot-payload.md. A runtime-prompt.md gets built alongside it: five baseline operating rules plus the profile's mental-model guardrails. The two get concatenated and piped straight into:

goose run --no-session --instructions - --output-format stream-json

The stream gets captured to run.log; an audit record (tokens, duration, endpoint) and a daily cost rollup get emitted, along with a Mode 1 (context-drift) decay signal via embedding similarity.

Every session is stateless (--no-session). The agent has no memory of its own: the Git ledger is the memory, reconstructed fresh into the boot packet every single time.

cycle: boot plus self-correction

cycle checkpoints first (commits whatever's on disk), launches Goose with the same packet-build-and-launch as boot, then scans run.log for repeated failure signatures.

No repeat, and it's done. A repeat trips the circuit breaker:

rollback: git reset --hard <last stable [arkaint-sync] commit> + git clean -fd
truncate error_history.log (breaker starts fresh)
recovery loop, up to N attempts, escalating each time:
   1st   try an alternative minimal fix
   mid   trace to the underlying systemic cause
   last  stop coding, write a summary for the operator

Each attempt rebuilds the packet with the corrective instruction, under the same profile, and relaunches. Success returns control; an exhausted budget means the operator has to step in.

Decay detection, running the whole time

Six named decay modes, four of them wired to actual detectors: Mode 1 (context drift) fires on every launch via bin/embed.py; Modes 2 and 4 (quick-fix accumulation, boundary violation) come from diffing consecutive [arkaint-sync] commits; Modes 3 and 5 (pattern blindness, repeated-failure looping) fire when the circuit breaker trips; the last ties to verify-spec.sh failures. Everything emits JSONL into .arkaint/audit/decay-*.jsonl, gitignored, but outside the rollback path, so the signal survives a git reset --hard even when the code it was measuring gets thrown away.

What sits outside the loop and enforces it

A .githooks/pre-commit hook rejects any commit touching scripts/ or .githooks/ unless ARKAINT_ALLOW_INFRA_EDIT=1 is explicitly set. The orchestrator can't quietly rewrite its own rules mid-run.

The one-sentence version

State lives in structured Git commits, not the model's context. Every launch reconstructs a bounded packet from the last three checkpoints, runs a stateless Goose session against it, and a heuristic circuit breaker rolls back to the last known-good commit and retries with an escalating instruction when the same failure repeats.