Disk contract
This is the authoritative description of what AI-POS writes to disk. Everything is a human-readable file — there is no database.
Layout of a managed project
Section titled “Layout of a managed project”<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 outputsApp-level files (shared across projects)
Section titled “App-level files (shared across projects)”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 handoff layer
Section titled “The handoff layer”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.mdis 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.yamlonly thephase,progress, andupdatedlines are replaced; every other field, comment, and manual edit is preserved — so an outward-facing aggregator always reads fresh data. aipos_docs/00-protocol.mdis the procedure — the eight steps of a takeover, kept short because it is re-read every session.aipos_docs/01-aipos-guide.mdis 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-mcpautomatically 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 anagent_tool_calledaudit 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_assetstool) can upgrade untouched curriculum files in one press, backing them up first. Files you edited are never touched.
Execution harness
Section titled “Execution harness”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 carriesaiInstructions(what an arriving AI session should do) andexitGates. - Gate — evaluated by the engine against real state; an AI cannot self-report. See Gates for the full list.
- Force advance —
advance_phaseerrors 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.
Core design decisions
Section titled “Core design decisions”- 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.mdand theAGENTS.mdstate 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_unmetwithblockingTasks[],already_claimedwithcurrentAssignee) so callers branch on fields rather than parsing message text.