# Kade v0.2 — Atlas side complete, ready for Riv

**From:** Forge
**To:** Larry
**Date:** 2026-05-24
**Status:** ✅ Schema applied · ✅ 7 endpoints landed · ✅ `/kade` web UI shipped · ✅ 15-test smoke pass · ⚠ Needs `pm2 restart atlas` (elevated) to deploy

---

## What shipped

| Layer | Artifact | Path |
|---|---|---|
| Migration | `009_kade_tasks` (applied to local Postgres) | `app/scripts/migrate_009_kade_tasks.mjs` |
| Shared lib | Validators, bucket caps, serializer, audit-log writer | `app/lib/kade-tasks.ts` |
| API | 7 endpoints under `/api/kade/tasks/*` | `app/app/api/kade/tasks/*/route.ts` |
| Web UI | `/kade` page + interactive board | `app/app/kade/{page,KadeBoard,actions}.tsx` |
| Nav | `Kade` tab added next to `Rounds` | `app/components/Nav.tsx` |
| Contract | API spec published for Riv on 2026-05-24 | `Team Inbox/_Handoffs/2026-05/2026-05-24 - Forge to Riv - Kade v0.2 Tasks API Contract.md` |

`next build` is clean. TypeScript clean. Smoke ran against a side-channel `next start` on `127.0.0.1:3030` — see "smoke results" below.

---

## Schema decisions worth flagging

### Unified the migration-006 scaffold
Migration 006 pre-baked **three separate empty tables** — `kade_tasks`, `kade_reminders`, `kade_list_items` — for v0.2/v0.3. After scoping v0.2 I collapsed all three into a single `kade_tasks` queue with a `bucket` enum (`top3`/`today`/`list`). Rationale: "Top 3 / Today max 8 / List From Hell" is a bucket discipline, not three separate tables. Reminders fold in via `due_at` + `snooze_until`; "lists" *are* the buckets. Zero rows lost (all three legacy tables verified empty before drop; no app or bot code referenced them).

### Bucket caps are server-enforced
- `top3` caps at 3 open tasks
- `today` caps at 8 open tasks
- `list` is uncapped
- POST/PATCH return `HTTP 409` with a clear `error` field when a cap is hit. Atomic with the mutation (inside transaction + `SELECT … FOR UPDATE` on rebucket).

### Vague-task discipline
- `clarity = 'vague'` tasks are forced into `bucket = 'list'`. Attempting to promote a vague task to `top3`/`today` returns 400 with a clear message — clarify first, promote second.
- The today rollup excludes vague tasks. They live in a dedicated `vague_pending` count and a `/api/kade/tasks/vague` inbox endpoint.

### v0.3/v0.4 reserved columns
Shipped now but unused — keeps the API surface stable when next milestones land:
- `snooze_until` (v0.3 DND)
- `sass_level` (v0.3 nudge tone)
- `calendar_event_id` (v0.4 GCal two-way sync)

### Deltas from Larry's 2026-05-21 brief
| Larry's field | What shipped | Reason |
|---|---|---|
| `priority` (int 1..3) | `bucket` enum | v0.2 memory specifies bucket discipline, not numeric priority |
| `recurring_rule` JSONB | not shipped | v0.3 habits concern, not v0.2 task capture |
| `dnd_critical` bool | not shipped | v0.3 DND concern; reserved `snooze_until` is the relevant slot |
| `notes` | `details` + `notes` | `details` = clarified body; `notes` = ongoing ledger |
| status `dropped` | status `cancelled` | naming preference, behaviorally identical |
| source enum values | aligned with Larry's brief + my additions | granular for Riv: `slack-text/slack-voice/slack-slash/web/email/agent/manual/kade-inferred/qordinate-import` |
| `original_input` | **shipped** (your idea, kept it) | cheap, preserves raw user input for "all I've got saved is…" recall |

---

## What Riv has to build

Contract dropped at `Team Inbox/_Handoffs/2026-05/2026-05-24 - Forge to Riv - Kade v0.2 Tasks API Contract.md`. Riv can start *now* — the API is live behind the local server and will deploy as soon as PM2 restarts.

**Three open questions Riv should answer before he gets too deep:**
1. Does v0.2 want bot-driven snooze (`status='snoozed' + snooze_until`)? My recommendation: yes; safe to layer in.
2. Should free-text Slack DMs default to `bucket='list'`? My recommendation: yes — promotion to today/top3 is Jimmie's explicit act.
3. What slash commands does Riv want? My guess: `/kade add`, `/kade today`, `/kade top3`, `/kade done <n>`, `/kade list`.

---

## Smoke results (15/15 pass against side-channel `:3030`)

| # | Check | Result |
|---|---|---|
| 1 | Create clear list task | 201, `task_id=1, bucket=list, clarity=clear` |
| 2 | Create vague slack-voice task | 201, `clarity=vague` |
| 3 | Create today task | 201, `bucket=today` |
| 4 | Dedup on `(source, external_id)` | 200, `deduped=true` |
| 5 | `/today` rollup shape | OK, all 3 lanes + counts |
| 6 | `/vague` inbox returns 1 | OK |
| 7 | Clarify vague + promote to today in one call | OK, `events_logged: [rebucketed, clarified]` |
| 8 | Reject vague→today (cross-field rule) | 400, clear error message |
| 9 | Complete via update (auto-sets `completed_at`) | OK, `events_logged: [completed]` |
| 10 | Fill today bucket to 8 | 6 × 201 |
| 11 | 9th today insert | 409, `"bucket 'today' is full (max 8 open tasks)"` |
| 12 | Bulk complete with partition | `{completed:[3], not_found:[4,999], already_done:[]}` |
| 13 | List `?status=done` | 2 done tasks |
| 14 | Log event with dedup | 201, `log_id=14` |
| 15 | No bearer | 401, `"unauthorized"` |

All smoke data was deleted post-test. Production tables are empty and ready.

---

## What's needed to deploy

**One command, elevated PowerShell on Minas:**
```powershell
pm2 restart atlas
```

The PM2 daemon is owned by an elevated session, so this shell can't restart it (EPERM on the RPC pipe — known constraint per `reference_atlas_runtime`). The `.next/` build is on disk and is the current build; PM2 just needs to swap in the new manifest.

After restart, verify:
1. Navigate to `localhost:3000/kade` — board renders (empty state with the create form).
2. From any shell with the bearer token:
   ```powershell
   curl -H "Authorization: Bearer $env:ATLAS_INGEST_TOKEN" `
        http://localhost:3000/api/kade/tasks/today
   ```
   Should return `{ok:true, ... counts:{top3:0,today:0,overdue:0,list_total:0,vague_pending:0}}`.

---

## What's still in scope but parked

- **Task detail page** (`/kade/[id]`) — v0.2 board has expand-in-place cards; a dedicated detail/edit page is nice-to-have, not blocking.
- **Project rollup view** mentioned in the 2026-05-21 brief — viewable today via `/projects` (the projects page already exists); cross-linking from `/kade` is a future polish.
- **Recurring tasks** — deferred to v0.3 alongside DND + kick-in-the-pants cadence.

---

— Forge
