Skip to content

Disk contract

This is the authoritative description of what AI-POS writes to disk. Everything is a human-readable file — there is no database.

<project>/
AGENTS.md AI session entry point (pure index + an engine-maintained state block)
CLAUDE.md Thin shell whose one content line imports AGENTS.md (Claude Code reads only this name)
project.yaml Outward-facing aggregate manifest (phase/progress/updated synced line by line)
aipos_docs/00-protocol.md The session operating protocol — short, read on every takeover
aipos_docs/01-aipos-guide.md Complete file-contract guide (headless operating rules)
aipos_docs/modules/<module>.md One guide per *enabled* capability module; a module that is off
ships nothing, so the listing says which modules apply here
memory/MEMORY.md Cross-session memory index (one fact per file)
work_record/_TEMPLATE.md Monthly work record template
.mcp.json Hub connection settings for the agent host
(AI-POS points this at the absolute path of aipos-mcp; no manual PATH setup)
.agents/skills/ General-purpose workflow skills (/align-scope, /wrap-up,
.claude/skills/ /adversarial-review, /handoff-check) — the same files in both
Written at init to BOTH .agents/skills/ and .claude/skills/ as identical
real files (not a symlink); customisable, and once customised never
overwritten, while pristine copies upgrade along with the engine
.aipos/
context.json Project metadata, goals, boundaries (versioned by schemaVersion)
rules.json AI operating rules + self-improvement flywheel (with revision history)
workflow.json Execution harness: phases, AI instructions, exit gates, current position
agent_access.json Hub tool authorisation (a master switch gates the hub; with it on,
reads need no grant and writes are an explicit per-tool allowlist)
modules.json Enabled capability modules (collab / team / specs).
File absent = none enabled
settings.json Workspace behaviour settings (auto-archive switch and day count).
File absent = on, 7 days
exchange/ Cross-project delivery envelopes (team module; created on first
publish): outbox/ published and awaiting routing,
inbox/ arrived from an upstream. One <box>/<id>.json per envelope; when
attachments are present their bytes live in a sibling <box>/<id>/ folder
orchestrator.json LLM model registry + routing policy (dormant layer; nothing writes
or reads this today, so the file is usually absent)
mcp.json MCP client registry (archived design; usually absent)
.gitignore Excludes machine-local and rebuildable files
(secrets.enc, index.sqlite, .mutex)
.mutex Cross-process mutation lock (empty file; released automatically on OS crash)
index.sqlite FTS5 full-text index (rebuildable derivative; excluded from backups)
secrets.enc Encrypted machine-local key-value store (created empty; sealed with
a key that never leaves this machine, so the file itself is excluded
from git and from backups — an export re-encrypts its contents under
the backup passphrase as .aipos/secrets.portable.enc instead)
ledger.jsonl Append-only event ledger
shipped_assets.json Content fingerprints of shipped engine curriculum
(the basis for telling "outdated" apart from "customised")
asset_backups/ Backups of curriculum files taken before an upgrade
snapshots/latest_handoff.md The full handoff snapshot
specs/<capability>/spec.md Current-state specs (specs module; human-readable, git-trackable, indexed)
tasks/ One JSON per atomic task (T-0001.json…)
tasks/T-XXXX/ Optional task artifact bundle: free-form artifacts plus
specs/<capability>/spec.md deltas, folded into the root specs/ on archive.
Deleting the task deletes this whole bundle
artifacts/ Deliverable outputs

Not everything lives inside a workspace. These sit in your home directory and are shared by every project on the machine:

~/.aipos/
registry.json The project directory behind the Projects home screen
teams.json The team graph: members, flow edges, canvas layout, auto-send flags
templates/ Custom workflow templates (drop a JSON file in to add or shadow a built-in)
agents.json The agent CLI catalog for the built-in terminal, including custom
entries and their environment variables (stored in plaintext)
terminals/ One JSON per persisted terminal session (metadata only — scrollback
is deliberately not kept across restarts)

The entry point is the root AGENTS.md, the filename any agent host can read. Claude Code reads only CLAUDE.md, so a thin shell there — its one content line is the @AGENTS.md import — pulls in the body: one place to edit, reachable from both. And it never goes stale:

  • The current state block in AGENTS.md is fenced by <!-- AIPOS:STATE:BEGIN/END --> and the engine rewrites it on every task, decision, and phase change (one-line situation, this phase’s instructions, gate checklist, next step, blockers, recent decisions). Handwritten content outside the block is never touched, and deleting the markers stops the engine touching the file at all.
  • In project.yaml only the phase, progress, and updated lines are replaced; every other field, comment, and manual edit is preserved — so an outward-facing aggregator always reads fresh data.
  • aipos_docs/00-protocol.md is the procedure — the eight steps of a takeover, kept short because it is re-read every session. aipos_docs/01-aipos-guide.md is the contract, read when it is needed: task and ledger JSON formats, gate semantics, headless advancement rules, the honesty principles, and which files must not be touched.
  • aipos_docs/modules/ holds one guide per enabled capability module. A module that is off ships no guide at all, so a workspace never carries the contract for a capability it does not have — and the directory listing agrees with the hub’s tool list by construction. Turning a module off leaves its file in place; it simply stops applying.
  • Hub tools: the Claude CLI connects to aipos-mcp automatically via .mcp.json (other vendors’ CLIs wire MCP up their own way); tasks, decisions, milestones, and advancement all go through tool calls. The engine keeps the ledger and handoff layer in sync, and every call — including denied ones — leaves an agent_tool_called audit entry. Gate overrides and manual confirmation are human-only and have no tool surface at all.
  • Legacy workspaces: Project settings → AI takeover layer → Fill missing files supplies whatever is absent (fills gaps only, never overwrites). Engine curriculum travels with the engine — the guide and the general-purpose skills record content fingerprints when shipped, so after an engine update the Tools page (or an agent, via the upgrade_workspace_assets tool) can upgrade untouched curriculum files in one press, backing them up first. Files you edited are never touched.

Every initialised project is a harness-driven state machine, not a pile of passive config:

  • Phase — defined by the template (plan → execute → review → post_mortem, for example). Each phase carries aiInstructions (what an arriving AI session should do) and exitGates.
  • Gate — evaluated by the engine against real state; an AI cannot self-report. See Gates for the full list.
  • Force advanceadvance_phase errors out when a gate has not passed. Forcing it requires a reason and is recorded to the ledger and history as an OVERRIDE.
  • Templates are data — five built-ins are embedded as JSON (bilingual: content follows the interface language, ids stay stable across languages, and a project is instantiated in whichever language is active at creation). Drop a JSON file into ~/.aipos/templates/ to add or shadow one, with no recompilation. The Templates page lets you add, edit, and delete custom templates visually.
  • Closed loop with the handoff — the snapshot’s first section states the current phase, and the third section opens with this phase’s instructions and gate list, so a new session immediately knows where it is, what to do, and what it has to pass.
  • Files are the source of truth. Tasks and settings are human-readable files: git-friendly, watchable. Indexes (SQLite FTS5, RAG) are only rebuildable derivatives.
  • Continuity contract. Every state change — task creation, transition, verification, decisions, milestones, rejections, phase advances, lessons — regenerates latest_handoff.md and the AGENTS.md state block. The snapshot is never older than the last operation.
  • No watcher feedback loop. The file watcher filters by allowlist (user-facing files such as tasks/, artifacts/, specs/, context and rules) and ignores the engine’s own derivative writes (snapshots, secrets, atomic temp files). The ledger is the one deliberate exception: an append emits its own signal — it feeds the notification surfaces but never means “re-read state”, and reading a tail writes nothing, so no loop closes.
  • Error model. One error type throughout — fallible paths return it rather than panicking — serialised as {kind, message} across both IPC and MCP. Collaboration rejections carry structured fields (dependencies_unmet with blockingTasks[], already_claimed with currentAssignee) so callers branch on fields rather than parsing message text.