# Tasks, observations, and handoffs


A cairn graph is built from three nouns. A **task** is a node: a date-prefixed slug with a status, a description, edges to other tasks, open metadata, and a stream of observations. An **observation** is the cheapest write you can make, one line of freeform text appended to a task. A **handoff** is a resumable summary: a scaffolded document whose one-line summary is the first thing the next session reads. These three are all you write. Everything else cairn shows you, from the frontier to the timeline, is computed from them.

Each noun maps to a verb you call and an event the call records. That is the shape of the whole system: a small, closed vocabulary of writes, each one durable, each one replayable. Understanding what each noun is, and what it is *not*, tells you when to reach for which.

## The task: a node with a date-prefixed slug

A task is identified by a slug minted from the name you give it. `task_create` over the name `wire up auth` yields a slug of the form `<today>-wire-up-auth` (the UTC date stamp followed by the slugified name) and returns `Created <slug>.`. The date namespace is system-owned. If you hand `task_create` a name that already carries a leading `YYYY-MM-DD-` prefix, it strips that before stamping today's, so the prefix never doubles and minting the same name twice in a day is idempotent. A name that recovers nothing descriptive is rejected before any event is recorded.

The slug is the address. Every other write names a task by slug or operates on the current one. A task carries:

- **a status** — one of `open`, `active`, `completed`, `abandoned`, `blocked`, moved with `task_update_status` (`<task> is now <status>.`);
- **a description** — the freeform line set at creation;
- **edges** — typed links to other tasks (`phase-of`, `depends-on`, `related`), added with `task_link` and removed with `task_sever`;
- **metadata** — open key/value pairs set with `task_set_metadata` (`Set <key> on <task>.`);
- **observations** — the append-only text stream described below.

`task_get` renders all of this for one slug: status, description, parent, children, edges, metadata, and the five most recent observations. Past five, it appends a one-line pointer to the rest — read a task's full observation history with `timeline(full=true, types=observation)`. None of it is a file you edit. The task is a projection of the events recorded against its slug, so the rendered node is always whatever the log replays to. See [Events, projection, and reconcile](/cairn/concepts/events-projection-and-reconcile).

Creating the first task adopts it as current when no current task is set; after that, `task_create` leaves the pointer alone. Forking with `task_fork` always switches the pointer to the child. The difference matters when you are building a plan, and it is covered in [The current task pointer](/cairn/concepts/the-current-task-pointer).

## The observation: the cheapest write, the heartbeat

An observation is one line of freeform text appended to a task. You call `observe` with `text`, it records an `observation` event, and it returns `Observed on <task>.`. That is the entire transaction. `observe` changes nothing but the observation stream and leaves your focus where it was.

This cheapness is the point. Because an observation costs nothing, the design assumes you record one whenever you learn something: a dead end you ruled out, the file and line where the real bug lives, a decision and the reason behind it. They are the running record of why the task moved the way it did. The store indexes them for full-text search, so an observation written today is what a future session retrieves with `task_search` when it asks "did anyone already look at this?" See [The cairn-method](/cairn/concepts/the-cairn-method) for the discipline and [`task_search`](/cairn/reference/tools#task-search) for the retrieval side.

An observation resolves to the current task unless you pass `task_id` to scope it elsewhere. Because it does not move the pointer, you can annotate a neighboring task mid-flow and stay on your own.

## The handoff: a resumable summary, summary first

A handoff is a document that lets a fresh session pick up where you stopped. You call `handoff` with a one-line `summary`; it mints a path under the task scratchpad, writes a skeleton document, records a `handoff.create` event, and returns `Handoff scaffolded for <task> at <path>`. The skeleton is deterministic: frontmatter, a `State` snapshot computed from the task, and empty `Recent work` and `Next steps` sections. The tool never drives an authoring turn. It hands you a valid file and a path; you read the scaffold and overwrite it with the rich body.

The `summary` is load-bearing: a resuming session reads it first and can often act on it without opening the file, so its precision matters more than the body's. It is also what `task_bootstrap` surfaces in its `handoffs:` block when you orient on the task.

Two surfaces write handoffs, and they are not the same:

- **The `handoff` tool** scaffolds the skeleton and records the event. It is deterministic and never authors prose.
- **The `/handoff` command**, under a kli host, is an authoring turn: it composes the one-line summary, calls the tool to scaffold and record, reads the scaffold, then overwrites it with a thorough document — task status, critical references, recent changes in `file:line` form, learnings, artifacts, graph state, and numbered next steps.

The tool gives you the durable record and the file; the command gives you the writing. Either way the summary comes first. See [Slash commands](/cairn/cli/slash-commands) for the `/handoff` authoring command and [the `handoff` tool](/cairn/reference/tools#handoff) for the scaffold it builds on.

## Three nouns, three events

Every write you make against the graph reduces to one of these nouns appending one event:

| Noun | Verb | Event recorded | Returns |
| --- | --- | --- | --- |
| Task | `task_create` | `task.create` | `Created <slug>.` |
| Task | `task_fork` | `task.create` + `task.fork` | `Forked <child> from <parent> (<edge>).` |
| Task | `task_link` | `task.link` | `Linked <src> -> <target> (<edge>).` |
| Task | `task_sever` | `task.sever` | `Severed <src> -> <target> (<edge>).` |
| Task | `task_set_metadata` | `task.set-metadata` | `Set <key> on <task>.` |
| Task | `task_update_status` | `task.update-status` | `<task> is now <status>.` |
| Observation | `observe` | `observation` | `Observed on <task>.` |
| Handoff | `handoff` | `handoff.create` | `Handoff scaffolded for <task> at <path>` |

Reads — `task_get`, `timeline`, `task_search`, `task_query`, and `task_bootstrap` — record no event. They project the log; they do not extend it. `task_bootstrap` in particular looks like a write because it can move the current pointer, but it records nothing: it switches focus and reads back state. The boundary between what extends the log and what merely reads it is enforced by capability, not by which tools are visible. See [Reads, writes, and capabilities](/cairn/concepts/reads-writes-and-capabilities).

## Why this shape

The three nouns are deliberately uneven in cost. A task is a commitment: it has a slug, a status, a place in the graph. An observation is nearly free, one line with no ceremony, because the friction of recording what you learned is the thing that loses knowledge between sessions. A handoff sits in between: more than a note, less than a meeting, a single document whose summary a tired or truncated reader can act on without opening it.

Keeping the write vocabulary this small is what makes a cairn graph durable and replayable. There is no rich task object to migrate, no handoff schema to version. There is a log of `task.create`, `observation`, `handoff.create`, and a handful of edge and status events, and the task you see is what that log folds to.

## Related

- [The task graph](/cairn/concepts/the-task-graph) — how tasks and their typed edges form the durable DAG these nouns live in
- [The current task pointer](/cairn/concepts/the-current-task-pointer) — which task an unscoped `observe` or `handoff` resolves to, and what moves the pointer
- [Events, projection, and reconcile](/cairn/concepts/events-projection-and-reconcile) — how each recorded event folds into the task you read back
- [The cairn method](/cairn/concepts/the-cairn-method) — the bootstrap → observe → handoff loop these nouns were built for
- [Slash commands](/cairn/cli/slash-commands) — the `/handoff` authoring command and the `handoff` tool it scaffolds with
