Skip to content

Local repositories

The Go reference implementation also creates a local .aip/AGENTS.md guide. It is editable instruction text, not a canonical object or required transport object. See agent instruction files for discovery and preservation.

aip init initializes the current directory with:

.aip/
HEAD
config
objects/<first 2 hex digits>/<remaining 62 hex digits>
refs/states/<state ID>
refs/intents/<intent ID>
index/
tmp/

The loose-object file is the exact canonical object, with no header, compression, or Markdown. Object IDs and files are immutable. Empty index/ is reserved for rebuildable reverse-lookup caches; current queries scan the CAS. tmp/ holds the write lock. Unrecognized object versions and repository formats fail explicitly.

config is exactly aip-repository-version=1\n. HEAD contains a full state ID and a single newline. A registry reference file contains its own full ID and a single newline. State and intent registry names are IDs, not mutable branch names. Registry entries retain candidates; they are not a chain of named tips.

Initialization creates the same canonical empty root state in every repository. Existing workspace files are not automatically captured. Init stages metadata in a sibling .aip-init-* directory and renames it to .aip after flushing it. A temporary .aip-init.lock directory excludes concurrent initializers. An existing .aip is an error and is never reinitialized.

Publication and concurrency

The reference implementation targets local filesystems supporting hard links, atomic same-filesystem rename, directory creation, and file/directory fsync. Network filesystem lock/atomicity behavior is outside the tested profile.

CAS writes use an exclusive temporary file in the destination prefix directory, write all bytes, set read-only permissions, fsync, then hard-link the completed file to its final name. Linking MUST NOT replace existing objects. If the target exists, its bytes and digest are checked; corruption is an error, never an excuse to overwrite it. The parent directory is flushed before success. Temporary files are removed; .write-* files left by crashes are ignored by enumeration.

Repository mutations acquire .aip/tmp/write.lock via exclusive mkdir. Contention fails explicitly, and the caller may retry. Snapshots hold it through observation, object publication, state registration, and HEAD update. CAS writes themselves are safe without this lock, including duplicate writes by concurrent processes.

A snapshot publishes artifacts, operation, and state in that order, validates the resulting graph, writes the state registry entry, then replaces HEAD. References use write/fsync/rename/directory-fsync. HEAD never points to partially written objects. Readers can see the old or new HEAD. No transaction covering several reference files is claimed. Readers resolving HEAD once use that resolved state for the rest of the command. They do not acquire the writer lock.

A crash may leave complete unreferenced artifacts, operations, states, or reported evidence, a registry entry with an old HEAD, or temporary files/locks. Such objects are immutable and can be inspected. History and reverse queries enumerate all valid CAS objects, including fully published candidates left before HEAD update. Registry files are publication bookkeeping; their absence does not invalidate an otherwise valid object. No automatic garbage collection or lock stealing exists. An operator may remove a stale lock only after ensuring no writer is active; init staging directories and .ref-*/.write-* files can then be removed too.

Reads and verification

Object lookup checks the full ID syntax, regular-file storage, size limit, SHA-256, canonical encoding, and schema. Graph verification additionally follows references, checks target types, rejects cycles/missing objects, checks operation before images and inputs, recomputes resulting file maps, and checks evidence membership. CLI object verification performs all of these checks.

The metadata directory is trusted local control data; hostile processes with write access to .aip are outside the local filesystem threat model. Object bytes remain untrusted for parsing and integrity purposes. Read-only mode bits are an accident guard, not a security boundary. No credentials, signatures, or ownership authentication are implied by a valid hash.

Repository discovery walks upward from the current directory. Commands invoked in subdirectories observe the full repository. .aip itself cannot be a symlink.

HTTP imports

The experimental HTTP server reuses this layout. It validates incoming objects and their complete dependency graphs before CAS publication; dependencies arrive first. Imports do not change HEAD, working files, or registry references. Registry references can subsequently be created/reaffirmed under the writer lock with the HTTP compare-and-swap precondition. Imports are immediately visible to CAS enumeration and reverse queries, even before a reference is published. There is no hidden staging area or atomic transaction over a whole transfer. Exposing a repository therefore exposes all of its stored objects to authorized readers, not just objects registered as states/intents. See http.md.