AGENTS.md · git:20260504.05bf818 · 2026-05-04 · sha256 3790c3ed22fa75f5
AGENTS.md git:20260504.05bf818A
Immutable. This exact content never changes and is served at /api/v1/blob/3790c3ed22fa75f5.
# Cairn — Project Orientation (TOC pattern)
Table of contents for agents working on this repo. Per OpenAI's harness
lesson — *"treat AGENTS.md as the table of contents"* — keep this file under
~150 lines. Real content lives in `docs/`.
## What this project is
**Cairn = state + context-loading layer for AI coding agents.** It curates
`.harness/ground/` (decisions, §V invariants, canonical-map, brand,
quality-grades), exposes that state via an MCP server, and ships a Claude
Code plugin that wires adoption + the daily flow inline.
The Claude Code plugin is the primary surface; the CLI (`cairn ...`) is the
bootstrap and debug entrypoint. There is no separate orchestration runtime
— the plugin uses Claude Code's built-in subagent dispatch.
## Document index
| What | Where |
|------|-------|
| Quick start + concepts | [`README.md`](README.md) |
| Layered architecture (locked) | [`docs/ARCHITECTURE.md`](docs/ARCHITECTURE.md) |
| Plugin spec — adoption phases, hooks, multi-dev enforcement (locked) | [`docs/PLUGIN_ARCHITECTURE.md`](docs/PLUGIN_ARCHITECTURE.md) |
| MCP tool surface — tool-by-tool reference | [`docs/MCP_SURFACE.md`](docs/MCP_SURFACE.md) |
| `.harness/` directory contract | [`docs/FILESYSTEM_LAYOUT.md`](docs/FILESYSTEM_LAYOUT.md) |
| License | [`LICENSE`](LICENSE) |
## Operator profile (apply when communicating with the operator)
| Trait | Behavior |
|-------|----------|
| Communication | Terse-direct. Lead with answer or action. No filler. |
| Decisions | Fast-intuitive. Don't present options unless explicitly asked. When the operator states a decision, treat it as final. |
| Explanations | Concise. Root cause in 1-2 sentences then the fix. |
| UX philosophy | Design-conscious. UX is equal in importance to functional correctness. |
| Vendor choices | Opinionated. Do not suggest alternative libraries / frameworks unless they avoid a real risk. |
| Env vars | The operator hates env vars. Hardcode model IDs and paths in code. |
| Tests | "Tests are shitware. Only E2E with real DB matters." Sensors + E2E smokes only — no unit-test framing. |
| Backward compat | The operator hates backward-compat shims. Hard cutovers only. |
| Mobile mode | When the operator is on mobile, `AskUserQuestion` options get truncated; switch to chat-mode A/B/C with concise option labels. |
| Caveman ultra mode | Active for chat replies. Documents stay in full English. |
## Hard rules
- All design decisions live in `docs/`. Drift between conversation and `docs/` is a bug.
- Locked architectural decisions in [`docs/ARCHITECTURE.md`](docs/ARCHITECTURE.md) (§1 layered model, §3 package contents) and [`docs/PLUGIN_ARCHITECTURE.md`](docs/PLUGIN_ARCHITECTURE.md) (§3 package layout, §17 multi-dev) are not reopened without explicit operator instruction.
- Never use Claude Code `PreToolUse` hooks — they can brick the session. SessionStart instructions + MCP tools only.
- Hardcode model IDs in code (no env vars). Hard cutovers only (no transition shims).
## Workspace layout
```
cairn/
└── packages/
├── cairn/ — umbrella + CLI bin (`cairn init/join/hook/...`)
├── cairn-core/ — state + context + MCP server + sensors + hook runners
├── cairn-frontend-claudecode/ — Claude Code plugin (manifest + hooks + skills + agents + commands)
├── cairn-frontend-stub/ — in-memory test adapter (internal)
└── cairn-lens/ — VS Code / Cursor extension (.vsix)
```
The technical packages currently use the historical `harness*` names; the
search-replace to `cairn*` lands as part of the public-repo initial commit.
## Smoke gate
```bash
pnpm install
pnpm -r build
for s in plugin-layout resolve-attention stop-hook events session-state \
status-line session-start handoff scope-index read-enrich init \
ingestion-baseline tier0 gc lock source-comments rules-merge join \
bypass-detection bootstrap-guard e2e-adoption e2e-daily-flow; do
pnpm --filter @isaacriehm/cairn "smoke:$s"
done
```
22 smokes; all should pass on a clean tree.
## Starting fresh
1. Read [`README.md`](README.md) end-to-end.
2. Read [`docs/ARCHITECTURE.md`](docs/ARCHITECTURE.md) — locked layered model.
3. Read [`docs/PLUGIN_ARCHITECTURE.md`](docs/PLUGIN_ARCHITECTURE.md) — plugin spec.
4. Skim [`docs/MCP_SURFACE.md`](docs/MCP_SURFACE.md) and [`docs/FILESYSTEM_LAYOUT.md`](docs/FILESYSTEM_LAYOUT.md).
5. Confirm to the operator in 2-3 lines what you've loaded.
6. Match the operator's terse-direct style.