# Built-in and user-defined views


A view is a named query: a label bound to a piece of [TQ source text](/cairn/reference/tq-language) that resolves to a set of tasks when you call `(query "name")`. cairn ships ten built-in views, expressed in TQ itself. They are the language's shipped vocabulary — `plan-frontier`, `leaf-tasks`, `stale-phases`, and the rest — and you read them on the read surface through [`task_query`](/cairn/reference/tools#task-query) or define your own through [`task_query_write`](/cairn/reference/tools#task-query-write).

Each built-in is data, not tool surface. The view's body is ordinary TQ, so you can read the definition with `(-> (views) (:where (= :origin "builtin")) (:select :source))`, copy it, and adapt it. A view defined under your own name shadows the built-in of the same name; remove the user view and the built-in reappears.

## Reading a view

Resolve any view by name with the `(query "name")` source:

```text
task_query  (query "plan-frontier")
```

The result renders as a task list — one line per task, slug first, then display name, status, and any counts the view enriched:

```text
2 tasks:
- 2026-06-20-write-the-parser (open) obs=3 edges=2
- 2026-06-20-wire-the-cli (open) obs=1 edges=1
```

`(query "name")` is a read. A view defined on the write surface still resolves on the read surface, because reading a view is a read regardless of how the view was created. Naming a view that does not exist is a structured error that enumerates every resolvable name — both built-in and user-defined:

```text
Query error: Unknown named query plan-fronteir. Available: active-roots, orphans, leaf-tasks, stale-phases, plan, plan-frontier, frontier, recent, busy, hub-tasks, knowledge.
```

## The ten built-in views

The table lists every shipped view with its TQ source text exactly as cairn defines it. `frontier` is an alias — its body is `(query "plan-frontier")` — so the eleven accepted names resolve to ten distinct queries.

| View | TQ source | Yields |
| --- | --- | --- |
| `active-roots` | `(-> (active) (:where (not (has :parent))))` | Live tasks with no parent — the roots of every open plan. |
| `orphans` | `(-> (all) (:where (= :edge-count 0)))` | Tasks with no edges in any direction: unparented, unlinked, unforked. |
| `leaf-tasks` | `(-> (active) (:where (= (count (:follow :phase-of)) 0)))` | Live tasks with no phase children — the bottom of the plan tree. |
| `stale-phases` | `(-> (active) (:where (any (:back :phase-of) (or (= :status "completed") (= :status "abandoned")))))` | Live phases whose parent has already settled, a sign the plan moved on without them. |
| `plan` | `(-> (current) (:follow :phase-of) (:or-else (-> (current) (:back :phase-of) (:follow :phase-of))) (:enrich))` | The phases of the current task's plan, enriched with counts. Current-scoped. |
| `plan-frontier` | `(-> (query "plan") (:where (and (not (or (= :status "completed") (= :status "abandoned"))) (all (:follow :depends-on) (or (= :status "completed") (= :status "abandoned"))))))` | The ready subset of `plan`: unsettled phases whose every `depends-on` dependency is settled. |
| `frontier` | `(query "plan-frontier")` | Alias for `plan-frontier`. |
| `recent` | `(-> (active) (:sort :updated-ts) (:take 20))` | The twenty most recently touched live tasks. |
| `busy` | `(-> (active) (:sort :obs-count) (:take 20))` | The twenty live tasks with the most observations. |
| `hub-tasks` | `(-> (active) (:sort :edge-count) (:take 20))` | The twenty live tasks with the most edges — the connectors in the graph. |
| `knowledge` | `(-> (current) (:closure :phase-of :depends-on :related) (:enrich))` | The transitive neighborhood of the current task across all three edge types, cycle-safe and depth-bounded. |

Three of these views read the `(current)` source — `plan`, `frontier`/`plan-frontier`, and `knowledge` — so they resolve against [the current task pointer](/cairn/concepts/the-current-task-pointer) and error when no task is selected. The rest range over `(active)` or `(all)` and resolve the same way in every session. The [TQ sources](/cairn/reference/tq-language#sources) table defines each producer.

### Built-in source forms in TQ

Each built-in is a complete TQ program, and every piece it draws on is documented in the [TQ language reference](/cairn/reference/tq-language). The [sources](/cairn/reference/tq-language#sources) are `(active)`, `(all)`, and `(current)`. The [steps](/cairn/reference/tq-language#steps) are `(:where)`, `(:follow)`, `(:back)`, `(:sort)`, `(:take)`, `(:or-else)`, `(:closure)`, and `(:enrich)`. Inside a predicate they reach across edges with the `(any TRAV P)` and `(all TRAV P)` quantifiers and count with the `(count TRAV)` field-expression. `plan-frontier` composes over `plan` by name, and `frontier` composes over `plan-frontier` by name, so a view defined in terms of another view resolves transitively.

A view defined in terms of itself is a structured error, not an unbounded loop. Define a view named `self` whose body is `(query "self")` and resolving it reports the cycle rather than recursing — `self` in the error text is the offending view name:

```text
Query error: View self is defined in terms of itself.
```

## `recent` is a view, not a source

`recent` is a view name, so you read it with `(query "recent")`. `(recent)` is not a source form. The query language has exactly ten sources — `(all)`, `(active)`, `(dormant)`, `(current)`, `(node "substr")`, `(query "name")`, `(schema)`, `(views)`, `(fields)`, `(edges)` — and `recent` is not among them. Calling `(recent)` as if it were a source is an unknown-source error that lists the ten known sources:

```text
Query error: Unknown source recent; known: active, all, current, dormant, edges, fields, node, query, schema, views.
```

The same holds for every other view name: `(plan)`, `(orphans)`, and `(busy)` are not sources. Reach a view only through `(query "name")`.

## Defining your own views

`define!` and `undefine!` are write forms — they record an event and are accepted only on the [`task_query_write`](/cairn/reference/tools#task-query-write) surface. The read surface refuses them:

```text
Query error: Mutations need the task_query_write surface; task_query is read-only.
```

### `define!`

```text
task_query_write  (define! "blocked-phases" (-> (active) (:where (= :status "blocked"))))
```

`(define! "name" Q)` validates `Q` read-only, records its source text as a `view.define` event, and returns `Q`'s tasks — so `define!` is interchangeable with the query it names. The view name must be a non-empty string. The query `Q` is evaluated read-only even on the write surface: you define over a selection, you do not mutate inside the definition. After the call, `(query "blocked-phases")` resolves on either surface.

### `undefine!`

```text
task_query_write  (undefine! "blocked-phases")
```

`(undefine! "name")` records a `view.undefine` event and returns no tasks. It removes the user view of that name. If a built-in of the same name exists, that built-in becomes visible again.

### Shadowing a built-in

A user view of a built-in's name shadows it in the one resolver. Define `orphans` over `(dormant)`, and `(query "orphans")` now returns settled tasks instead of edgeless ones; `undefine!` it and the built-in `(-> (all) (:where (= :edge-count 0)))` resolves again:

```text
task_query_write  (define! "orphans" (dormant))
task_query        (query "orphans")          # now resolves to your definition
task_query_write  (undefine! "orphans")
task_query        (query "orphans")          # the built-in is back
```

A view is a fold of `view.define`/`view.undefine` events, so a rebuild reconstructs your views exactly. See [events, projection, and reconcile](/cairn/concepts/events-projection-and-reconcile) for how the view vocabulary replays from the durable log.

## Listing every view

The `(views)` [source](/cairn/reference/tq-language#sources) produces every resolvable view as a queryable node-set. Each view node carries an `:origin` of `builtin` or `user` and a `:source` field holding its TQ text, so you can filter and project the catalogue with the algebra itself:

```text
task_query  (-> (views) (:where (= :origin "builtin")) (:ids))
```

```text
task_query  (-> (views) (:where (= :origin "user")) (:select :source))
```

A built-in shadowed by a user view of the same name reports once, as `user` — `(views)` reflects what resolves, not what ships.

## Related

- [TQ language](/cairn/reference/tq-language) — the sources, steps, and predicates every view is written in.
- [Plans, phases, and the frontier](/cairn/concepts/plans-phases-and-the-frontier) — why the frontier is the ready subset of a plan.
- [Tools](/cairn/reference/tools#task-query) — the `task_query` and `task_query_write` wire surface.
