Missions
The mission always comes first
Overview
This is the tab the app opens to. At the top, the Olivium counter and today's status pill (NOT STARTED YET / IN PROGRESS / PAUSED / ALL DONE). Below the banner, a horizontal scroll of MissionCards — tap one to set it active and dive in. Below that, today's goals as a vertical list: each row has a play / stop button, an optional time estimate, and the checkpoint it belongs to. The day's date pill at the top right opens a DatePickerSheet so the agent can plan tomorrow or audit yesterday.
How it works
Three live Convex queries run in parallel: `missions.list` (all of the agent's missions), `missions.getActive` (which one is the working mission), and `goals.listByUserAndDate` (today's tasks, filtered by `scheduledDateISO`).
On every mount, we fire two idempotent mutations: `goals.backfillScheduledDateISOForUser` (one-time for legacy goals without the ISO date field) and `goals.ensureRecurringForDate` (instantiates any recurring tasks for the selected day).
Mission cards are height-equalized: each card reports its rendered height via `onLayout` into a ref map, and the tallest height is applied as a `minHeight` to every card. The result is a clean horizontal row even when names wrap differently.
Tapping play on a goal routes to `/focus/[taskId]`. Tapping stop transitions the task to `paused`, opens an AlertSheet, and if confirmed runs `goals.update` with status=done. Done goals fall to the bottom and stay faded.
The day status pill is computed locally from the goals array — `all done`, `in progress`, `paused`, or `not started yet` — and color-coded with the design-system tokens (`sage`, `highlight`, `progress`).
The 'Take a break' tile opens the BreakSheet. 'Distractions' is locked. 'Senses' is coming-soon.
Key decisions
Today is the default, but not a prison
The date pill defaults to TODAY but lets the agent scroll any direction. Yesterday's day is still viewable — we don't hide your past. Tomorrow lets you plan ahead. Both reuse the same goals query, just with a different `dateISO`.
Idempotent backfills on every mount
Adding `scheduledDateISO` to the tasks schema was a backwards-incompatible change for existing data. Instead of running a one-shot migration we wired the backfill into the screen mount — it's idempotent, cheap, and means the data heals itself as users open the app.
Recurring tasks instantiated lazily
A goal that repeats daily isn't 365 rows in the database — it's a 'source' row plus on-demand instances created the first time you view a future date. `ensureRecurringForDate` materializes them per day, which keeps the table size honest and means edits to the source propagate forward.
Mission cards as carousel, not list
Long-term goals deserve to be one-at-a-time. A vertical list of five missions encourages context-switching; a horizontal carousel forces the agent to pick which one is today's. That's why the carousel sets the active mission on tap.
