---
name: capture
description: >
  Passively extracts decisions, ideas and tasks from conversation and proposes
  them as ledger rows. Fire on: "capture that", "note this", "log this
  decision", "add a task", "remind me to", "I need to", "we should", "let's go
  with", "decided", "park that", "someday", "I'm waiting on", or whenever the
  founder states a ruling, a commitment, a deadline or an idea in passing.
  Also fires at close to sweep the session for anything missed. NOT for:
  running the open or close itself (use session-ritual), deciding whether an
  insert is allowed (use approval-lattice — inserts are create-class), or
  storing long documents, which belong in files, not the ledger.
---

# Capture

The ledger only works if nothing said in chat is lost. Listen for
obligations and rulings while the conversation is about something else, and
propose them as rows. Inserts are create-class: propose, then wait for a yes.

## What to listen for

| Heard | Becomes |
|-------|---------|
| "I need to...", "remind me to...", "we have to..." | a `tasks` row |
| "let's go with B", "decided", "yes, do A" | a ruling: update `decisions`, plus a `ruling` event |
| "should we A or B?" left unanswered | a `decisions` row with options |
| "I'm waiting on..." | a `tasks` row, status `waiting` |
| "someday...", "park that", "not now but..." | a `tasks` row, status `someday` |
| "we started X but didn't finish" | an `open_thread` event |

## Fields to fill well

- **owner** — `founder` if only the founder can do it; `system` if you can.
- **next_check_at** — a real date when one is implied ("by Friday" → the day
  before). Otherwise leave it null and the trigger sets 7 days.
- **due_at** — only for a real deadline the founder stated.
- **priority** — `high` only if the founder said so or it has a near deadline.
- **unblocks** — true if other work is waiting on it.
- **horizon** — only if the founder has named the goal it serves.

## INSERT shapes

Task:

```sql
insert into tasks (title, status, priority, owner, next_check_at, due_at, unblocks, horizon, notes)
values ('<verb-first title>', 'next', 'med', 'founder', null, null, false, null, 'Captured: <session label>');
```

Decision with options:

```sql
insert into decisions (title, context, options, recommended, owner)
values ('Decide: <question>', '<why it matters, one line>',
        '["A: ...", "B: ...", "C: ..."]'::jsonb, '<letter> — <why>', 'founder');
```

Ruling on an existing decision:

```sql
update decisions set status = 'decided', chosen = '<option>', response = '<founder''s words>'
where id = '<decision id>';
```

Open thread or question:

```sql
insert into session_events (session_label, kind, body, refs, owner)
values ('<session label>', 'open_thread', '<one line>', '{}'::jsonb, 'system');
```

## How to propose

Batch captures. Do not interrupt every sentence. At a natural pause, or at
close, show a short list and ask once:

> Capture 2 items? (1) task: "Renew the office lease", founder, due Fri,
> high. (2) decision: "Decide: hosting provider", options A/B/C, recommend A.

## Rules

- Titles are verb-first and make sense without the conversation.
- Record the founder's own words for rulings in `response`.
- Never capture the same thing twice; check the ledger first if unsure.
- Long material goes in files; the row holds a one-line pointer in `notes`.
