You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Epic: Rebuild Omi Tasks around quiet capture, focused goals, persistent workstreams, and contextual action
Summary
Omi should not compete with ordinary task managers by extracting more todos. Omi should use what it knows about the user to identify meaningful commitments, preserve the context around ongoing outcomes, and help move the right work forward at the right moment without becoming noisy.
This epic replaces the current collection of partially connected task, goal, staged-task, notification, and task-chat behaviors with one product model:
Goal = why. Workstream = accumulated intelligence and continuity. Task = next concrete action. Agent = the mechanism that advances the work.
The intended experience is calm and opinionated:
Omi captures broadly and quietly.
Omi interrupts rarely and only when timing materially changes the value of acting.
Omi shows at most three “What matters now” recommendations at once.
Omi explains why an item matters now.
Omi prepares useful work—drafts, research, briefs, plans—inside a persistent workstream instead of starting from scratch for every task.
Omi learns from a tiny feedback vocabulary, never a survey.
This is a prescriptive implementation plan. Future implementers MUST preserve the product principles and sources-of-truth decisions below. If a phase must be split, split the delivery—not the invariants.
Scope and rollout decisions (locked for this epic)
macOS-first. Initial UI ships on macOS only, to the same whitelist cohort as the canonical memory system. Backend changes are universal; no mobile UI changes in this epic. Whitelist users get an intentionally incomplete mobile experience during rollout. Mobile/web/other surfaces: Follow-up: Tasks/Goals/Workstreams on mobile, web, and non-macOS surfaces #9359 (blocked by this epic).
Built on canonical memory only. Workstream evidence and association are built against the canonical Memories store (memory_items, INV-MEM-1/2/3) — never against legacy memory reads. Ship to the memory-whitelist cohort; do not build a legacy-memory compatibility path that would immediately be deleted.
Compressed AI-driven build, human taste gates. Target ~5 days total through prod for the whitelist cohort: build all phases fast; ship gates are (1) maintainer dogfood on macOS, (2) beta channel, (3) prod. The dates are targets; the gates are binding — if dogfood surfaces an auto-accept precision or interruption problem, the calendar slips, never the gate. The off | shadow | write | read machinery below still exists per user — it is the safety mechanism, not a calendar.
Interruption is earned, not scheduled. Dashboard intelligence and quiet capture ship first. Proactive interruptions (Phase 6) stay dogfood/opt-in until dashboard metrics demonstrate usefulness; the daily budget is a ceiling, not permission to send.
Day-1 hero experience: silent commitment capture (scenario 1), composed with the evolving draft into one golden-path loop (scenario 13) — capture → open → “Work on this with Omi” → draft → new evidence → cited v2 → resurfaced in What Matters Now. That loop is the dogfood script and the canonical E2E.
Product thesis
The user does not need Omi to produce a longer list. The user needs Omi to reduce cognitive load and make meaningful progress.
The north-star behavior is:
Omi observes a possible commitment or useful next step.
It captures the evidence without interrupting.
It connects the item to the relevant person, goal, workstream, conversation, and artifacts.
It decides separately whether the item is real, valuable, and worth surfacing now.
When useful, it prepares or performs the next reversible step through a persistent agent thread.
It asks for attention only when the expected benefit exceeds the interruption cost.
We are optimizing for user-validated, Omi-assisted advances per active week — value actually created — with proactive interruptions per advance as the efficiency guardrail. Not tasks extracted, notification clicks, or list size. A ratio alone is not the north star: suppressing all interruptions makes a ratio look perfect while the product does nothing.
Taste and non-negotiable product principles
1. Quiet capture; selective interruption
Discovery and notification MUST be separate settings and separate decisions.
Task discovery continues when proactive task notifications are off.
Candidate creation never triggers a notification by itself.
High-confidence explicit commitments may be added silently.
Inferred or ambiguous items remain candidates.
System/floating notifications require a distinct attention decision.
Task notifications MUST NOT bypass the global notification frequency, snooze, focus, or attention-budget rules.
The current coupling in TaskAssistant.isEnabled and TaskPromotionService must be deleted: task analysis is gated on task notifications, while promoted tasks bypass frequency throttling.
2. “What matters now” is not another task list
The primary intelligent surface ranks next best moves, not rows. It may select a task, a draft needing review, a decision, a blocked agent run, or a workstream that changed materially.
It shows at most three items. Each item must answer:
What changed or why now?
What outcome does this support?
What is the smallest useful next action?
What can Omi prepare or do?
The full Tasks page remains the control surface and archive. It must not become the primary expression of Omi’s intelligence.
3. Goals are durable outcomes, not interests and not an arbitrary top-three list
Goals represent longer-lived outcomes the user cares about achieving. Examples:
Launch the next Omi desktop release.
Build a reliable investor pipeline.
Improve cardiovascular health.
Goals are not generic interests such as “AI” or “health”; those belong in the user profile. Goals are also not individual next actions; those are tasks.
Users may have many goals. Only a small number—default maximum five—may be focused at once. Adding a sixth goal MUST NOT silently deactivate the oldest goal. Background, paused, achieved, and abandoned goals remain available as context and history.
4. Workstreams are the missing durable middle
A workstream is an evolving body of work that accumulates context over time. It can belong to a goal, but a lightweight workstream may exist without one.
Examples:
“Investor outreach to Sarah” under “Build investor pipeline.”
“Omi macOS task intelligence redesign” under “Launch the next desktop release.”
“Cardiologist appointment and follow-up” under “Improve cardiovascular health.”
A workstream owns:
A durable objective and current-state summary.
Relevant people, conversations, files, links, and evidence.
A chronological event journal.
Versioned drafts and other artifacts.
Open questions and decisions.
Current tasks and proposed task changes.
One resumable agent conversation per local runtime, plus child runs/delegations.
Tasks do not own agent continuity. Task chat becomes a view into the task’s workstream. If a plain task has no workstream, the first investigation/execution may explicitly promote it into a workstream; do not silently create hundreds of empty workstreams during extraction.
Workstreams come into existence three ways, and only three — and none of them is a user-facing “create workstream” action:
User intent via “Work on this with Omi.” The user invokes it on a task (or on a goal, which creates an anchor task first). The action silently establishes the internal workstream. There is no “Start workstream” button — that label would leak the noun 4b prohibits.
Accepted workstream candidate. Agent proposals and consolidation proposals flow through the universal candidate lifecycle (see Task candidate — subject_kind = workstream), rendered as an ordinary Suggested card. Accepting it creates the workstream plus its first anchor task in one transactional, idempotent resolution.
Consolidation recurrence (cold start). When memory consolidation observes repeated short-term evidence about the same unresolved open loop across days, it emits recurrence evidence; the workflow domain — never the memory system — turns that into a workstream candidate (path 2). This is the primary answer to "who creates the first ten workstreams" — not manual user effort. One-off mentions never qualify.
4b. Noun budget: the UI vocabulary is Goals and Tasks — nothing else
Goal and Workstream are different concepts and must not be merged in the domain model (a goal is a durable outcome; a workstream is a body of work with continuity; lightweight workstreams may have no goal). But the user-facing vocabulary has exactly two managed nouns: Goals and Tasks.
The workstream is never a noun the user creates, names, or browses in a top-level list. It renders as the thread behind a task (open a task → its ongoing conversation, drafts, journal are just there) and as sections of a goal (goal detail shows its active threads as structure of the goal).
The entry affordance is “Work on this with Omi” (label may be tuned in dogfood, but it must express intent — never expose the entity). No “Start/New workstream” wording anywhere in UI.
Do not build a "Workstreams" tab or list surface. The moment one exists, the product has three managed nouns and the calm is gone. Candidates surface as a "Suggested" lane inside Tasks, not as a fourth noun.
Keep "workstream" as the internal/API name. If a UI label is unavoidable, use "Thread"; prefer no label.
5. Agents prepare continuously but mutate cautiously
Within a workstream, agents may autonomously:
Read already-authorized scoped context.
Summarize new evidence.
Maintain the workstream’s current-state summary.
Produce versioned local drafts, research, briefs, and plans.
Propose task creation, edits, completion, or supersession.
Agents MUST NOT silently:
Send messages or emails.
Make external commitments.
Delete user data.
Mark a task complete without explicit evidence or user instruction.
Rewrite a canonical goal or task based only on model inference.
External writes and consequential mutations continue through coordinator dispatch/grant policy. Explicit, unambiguous user commands may use the existing policy-authorized direct-mutation path.
6. Feedback stays tiny
At any decision step the UI shows no more than three choices.
The standard recommendation actions are:
Do now
Later
Dismiss
After Dismiss, an optional second step shows exactly three reason chips:
Already handled
Not mine
Not useful
Dismiss-without-reason remains valid. Silence is not negative feedback. Do not add a longer taxonomy to the UI; richer internal outcomes must be derived from these three reasons and observed state transitions.
Current-state problems this epic must remove
The implementation is not starting from zero, but the existing parts disagree about authority and lifecycle.
Desktop relevance is mostly backstage.TaskPrioritizationService ranks only local staged tasks. The visible Tasks page then sorts action items by due date and creation time.
Pipelines disagree. macOS screenshot extraction stages and ranks candidates; backend conversation extraction writes directly to action_items; manual/chat/integration creation follows other paths.
Extraction policy disagrees by surface. Desktop treats “Sure, will do” as a high-value commitment; the backend conversation prompt may skip “I’ll do X” as immediate action.
The shared action-item contract is too thin. The desktop local model holds source, confidence, app/window, evidence context, tags, relevance, recurrence, goal, and agent fields. The backend API drops or ignores many of them. Sync can erase local intelligence.
Task→goal links are not canonical. Mobile stores links in local preferences. Desktop sends goal_id, but the current backend action-item update contract does not accept it.
Goals are rigid numeric trackers. The backend requires goal type and numeric bounds, caps active goals, and deactivates the oldest goal when the cap is reached.
The staged queue is not a user review queue. It is invisible and auto-promotes on a timer. A declared target count is not enforced as a real cap.
Promotion/dedup lifecycle can drift locally. Backend staged state and local staged SQLite are not one authority, allowing already-promoted candidates to continue influencing local dedup/ranking.
Feedback is not attributable enough. Task analytics records aggregate counts/source; notification analytics cannot reliably connect the interruption, candidate rationale, task disposition, and later outcome.
Task chat restarts at the wrong boundary. The desktop runtime has canonical sessions/runs/artifacts/context packets, but product task chat is keyed to a task instead of a durable body of work.
Every replaced path must be deleted after migration. Do not preserve legacy extraction/promotion behavior as a permanent fallback.
Canonical product model
Goal
Canonical backend-owned product state:
goal_id
title
desired_outcome
why_it_matters
success_criteria[]
horizon_at? # optional target horizon, not a mandatory task deadline
status = background | focused | paused | achieved | abandoned
focus_rank? # present only for focused goals, unique within user
metric? { type, current, target, min?, max?, unit? }
source = user | ai_suggested | imported
created_at
updated_at
ended_at?
Rules:
Metric is optional. Qualitative goals are first-class.
Focused goals are capped at five by default; all goals are not capped.
Moving a goal into focus requires an explicit replacement choice when the focus set is full. Never deactivate the oldest implicitly.
Goal progress is a journal of evidence-backed changes. A single percentage is a projection, not the only truth.
Workstream
Canonical backend-owned product state:
workstream_id
goal_id?
title
objective
status = open | paused | completed | archived
current_state_summary
next_review_at?
last_meaningful_progress_at?
latest_event_sequence
created_at
updated_at
event_id
sequence
kind = user_note | conversation | message | screen_observation | task_change |
decision | agent_update | artifact_version | external_update | system
summary
evidence_refs[] # first entry is the triggering source — there is no separate source_ref field
sensitivity
created_at
EvidenceRef is one typed shape used everywhere — journal events, candidates, artifacts, and decision records all carry the same type. Do not invent per-surface ref variants:
EvidenceRef {
kind = conversation | memory_item | workstream_event | artifact | chat_message | local_screen | external
id # canonical ID in that domain
version? # pin for mutable targets (e.g. memory items) so evidence reproduces reliably over time
scope = canonical | device_local # local_screen is always device_local
device_id? # required when scope = device_local
excerpt_hash? # integrity check without storing content
}
Scope rules: a device_local ref without device_id is invalid everywhere. Backend/canonical stores may persist device_local refs (with device_id) but consumers on other devices must degrade gracefully — render the event summary, mark the evidence as available on <device>, and never fabricate or block on it.
Do not synchronize raw screenshots into the backend workstream journal. Persist minimized summaries and evidence references under existing privacy policy. Local screen evidence remains local unless the user explicitly authorizes broader sharing.
Evidence references reuse the canonical memory provenance vocabulary — no parallel memory system.evidence_refs[] point at Conversations and canonical memory items via the typed EvidenceRef above, which subsumes the memory domain model's evidence[].source_id pattern (docs/memory/domain_model.md). A workstream journal entry that summarizes a conversation cites the Conversation; one that leans on a durable fact cites the memory item. Workstreams are Workflow in the memory glossary's terms — they are not a memory tier, never appear in Memories UI, and must not duplicate conversation or memory content into their own store (summaries + refs only). This keeps one provenance graph across memory and workflow (INV-MEM-1 vocabulary applies; do not invent new tier-like concepts).
Task
users/{uid}/action_items/{task_id} remains the compatibility collection during rollout, but its canonical schema is expanded:
task_id
description
status = active | completed | cancelled | superseded
goal_id?
workstream_id?
owner = user | other | unknown
due_at?
due_confidence?
source
provenance[]
priority?
sort_order
indent_level
created_at
updated_at
completed_at?
superseded_by?
Rules:
A task has at most one primary workstream and one primary goal.
If both are present, workstream.goal_id and task.goal_id must agree. Enforce this server-side.
Unlinked inbox tasks are allowed.
Relevance and attention scores are evaluations, not canonical task state.
Preserve compatibility fields during rollout, but stop encoding important semantics in opaque metadata JSON once typed fields exist.
Candidate (universal review lifecycle)
Replace staged_tasks with one universal Candidate lifecycle — the internal name is "Candidate", not "task candidate". The payload is a discriminated union on subject_kind: exactly one typed payload is present, so implementations cannot drift on a generic proposed_change blob:
candidate_id
subject_kind = task | workstream # discriminates the payload — exactly one of the two below is present
proposed_action = create | update | complete | cancel | supersede # workstream candidates: create only in v1
task_id? # required for task update/complete/cancel/supersede
task_change? # typed payload when subject_kind = task
workstream_proposal? { # typed payload when subject_kind = workstream
title
objective
anchor_task # typed as the canonical task-create payload (same shape as task_change for create)
}
capture_confidence
ownership_confidence
goal_id? # SINGLE authority for the proposed goal link — never duplicated in a payload
workstream_id?
evidence_refs[] # SINGLE authority for candidate evidence — never duplicated in a payload
source_surface
status = pending | accepted | rejected | expired
resolution_reason?
created_at
resolved_at?
Envelope vs. payload authority: the envelope owns capture metadata (goal_id, evidence_refs, confidences, source_surface); the payload owns only the proposed object's own fields. No field may appear in both.
Rules:
Explicit user commands may skip candidate review under policy.
High-confidence explicit commitments may auto-accept silently.
Unaddressed requests and model-inferred tasks remain pending.
Agent-proposed mutations use the same candidate type.
Workstream proposals (subject_kind = workstream, from accepted agent proposals or consolidation recurrence) use this same lifecycle and render as ordinary Suggested cards; accepting one creates the workstream plus its first anchor task in one transactional, idempotent resolution — never two independent writes.
Candidate resolution is idempotent and transactional with canonical task/workstream mutation.
Evaluations and attention decisions
The evaluation architecture is facts in, gates around, one judgment in the middle, trace out. Do not build a decomposed multi-component scoring formula that other code computes against — that is explicitly rejected. The model judges holistically; deterministic code supplies inputs and enforces policy.
Facts (deterministic inputs, computed by code, verifiable):
days_to_due? # from canonical due_at
someone_blocked # derived from evidence/dependency signals
has_concrete_next_action # is there a specific executable step?
focused_goal_linked # task/workstream links to a focused goal
context_match_signals[] # current app/person/document/meeting matches (macOS)
capture_confidence # from the candidate, set at extraction time
Facts are inputs to the judgment, never model outputs. They do not decay as models improve.
Gates (deterministic policy, never model-shaped): the attention gates in the “What matters now” section below. Budgets, quiet hours, dedupe, and thresholds are code.
Shortlist (deterministic, before any model call): a deterministic eligibility stage narrows the candidate set to roughly 10–20 items using facts only — open/unexpired, passing the recommendation eligibility gates (never the interruption gates — see the two gate sets below), recent material activity or due-window. The shortlist filters, never ranks; the moment it scores, the rejected component contract has been rebuilt upstream.
Judgment (one holistic model call): given the shortlist, the facts, the user's feedback history, and current context, the model selects ≤3 items and writes headline / why-now / recommended action. There are no separately-computed component scores (urgency, personal_value, goal_alignment, etc.) persisted as a typed contract. The public contract is the output (recommendation card shape, dedupe key, expiry) plus the gates — not the model's internal reasoning.
Decision record (auditable, versioned, for debugging and attribution only). Do not store raw model reasoning text — chain-of-thought is unstable across model versions and is exactly the raw private content this epic forbids logging:
evaluation_id
subject_kind / subject_id
shortlist_ids[] # exact candidates considered
facts_snapshot # the deterministic inputs above
prompt_version / policy_version / fact_definition_version / model_version
decision_summary # concise, bounded; not chain-of-thought
reason_codes[] # bounded, non-contractual — no system may branch on them
evidence_refs[]
final_output_ref
evaluated_at
expires_at
The decision record powers QA/debug tooling and feedback attribution. No system outside debug tooling may parse or branch on decision_summary/reason_codes — if the codes grow a consumer, the component-score taxonomy has returned through the back door. When a better model ships, swap the judgment and rerun the golden fixtures — no schema migration.
Testing: judgment quality is verified by golden ranking fixtures ("given this user state, these items must surface / must not surface"), not component-level score assertions. Fixture runs in CI are hermetic (recorded/stubbed judgments per repo testing rules); live-model quality evals run in a separate versioned evaluation workflow, not CI.
What matters now is a derived projection over canonical goals/workstreams/tasks, agent open loops, artifacts, context, and these evaluations. It is not persisted as task order and is never a source of truth.
Workstream agent binding
Execution truth remains in the desktop TypeScript runtime kernel and omi-agentd.sqlite3:
One reusable kernel conversation per (owner, device/runtime, workstream_id).
Child work uses normal AgentRun/RunAttempt/delegation records.
Swift remains a projection and event source.
Do not create a second agent lifecycle in Firestore or GRDB.
The backend stores product workstream state, event summaries, and artifact descriptors/checkpoints. It does not become authoritative for local run success/failure. A second device reconstructs context from the canonical workstream journal and continuation checkpoint, then establishes its own local runtime binding.
The existing kernel desktop_task_candidates table remains the auditable local proposal/outbox for agent-originated mutations; it is not a second product review authority. Delivery creates or resolves the backend canonical task candidate idempotently, records the backend candidate ID/receipt in kernel events or artifact-delivery metadata, and projects the canonical resolution back into the local action queue. Do not leave independent “pending” states in both stores.
Task chat behavior:
Linked task → open the workstream conversation and scope the UI to the task.
Unlinked task → offer “Work on this with Omi” on first investigation/execute, which silently establishes the workstream; simple questions may remain a lightweight task turn without durable workstream creation.
Navigating between tasks in the same workstream MUST preserve one conversation and artifact history.
New evidence updates the workstream journal; the next run receives a minimized context packet containing current state, relevant recent events, task, and current artifact heads.
Capture and promotion policy
Observation
Canonical outcome
Interruption
Explicit “add/remind/create task” command
Create task immediately
Confirm in the invoking surface only
Clear user promise with concrete deliverable and owner
Auto-accept silently when confidence threshold passes
Desktop screen extraction and backend conversation extraction MUST consume one shared policy specification and shared eval fixtures. Prompts may differ by modality, but commitment semantics and expected outcomes may not.
Workstream association (the hard problem — do not hand-wave it)
“New evidence updates the workstream journal” hides the hardest ML problem in this epic: given new evidence, which existing workstream (if any) is it about? If association precision is poor, journals fill with noise and current-state summaries stop being trustworthy; if it is too conservative, workstreams go stale. Treat association quality as a first-class deliverable with its own eval fixtures, equal in rigor to the capture fixtures.
Memory clusters by entity and fact similarity; workstreams cluster by intent and outcome. “This conversation mentions Sarah” does not mean “this belongs to the investor-outreach-to-Sarah workstream” — the association step must discriminate intent, not just entity overlap.
Prescribed pipeline (reuse the canonical memory system; only the adjudicator is new)
Extraction (already exists): the canonical memory pipeline already extracts entities, topics, and short-term items from each new Conversation. Reuse its outputs; do not build a second extraction pass.
Retrieval (existing pattern): embed each open workstream's objective + current_state_summary in a derived, rebuildable index (authority table: search/vector indexes are never canonical). Retrieval follows the INV-MEM-2 shape — vector hits are candidate workstream IDs only, hydrated against authoritative workstream records before use; fail closed.
Adjudication (the only new model step): an LLM call receives the new evidence summary plus the top-k (~5) candidate workstreams' current-state summaries and answers two questions: does this belong to one of these workstreams, and is it material (does it change state, stale a draft, or unblock something)? Non-material matches append nothing. No match appends nothing — evidence is never force-assigned.
Materiality → journal: only material, matched evidence becomes a workstream event (summary + evidence refs). Immaterial matches may update retrieval features without a journal entry.
Cold start
Workstream creation proposals come from memory consolidation recurrence (see principle 4): consolidation emits recurrence evidence when the same unresolved open loop repeats across multiple days, and the workflow domain turns it into a subject_kind=workstream candidate — the memory system never writes workflow objects. One-off mentions never qualify. This is deliberate — association has a small candidate set to adjudicate against precisely because workstreams are few and meaningful.
Acceptance
A golden association fixture set (evidence → expected workstream / no-workstream / immaterial) exists in Phase 0 and gates every prompt/model change.
“Sarah at dinner” does not land in the investor-outreach workstream (entity overlap alone never associates).
Rapid low-signal evidence (tab switching) produces no journal churn.
Association runs only for canonical-memory-cohort users; there is no legacy-memory association path.
“What matters now” behavior
Inputs
Focused and background goals.
Open workstreams and their recent material events.
Active tasks and candidates.
Due dates and deadline confidence.
Commitments to other people and dependency signals.
Current app/window/document/person context on macOS.
Calendar availability and upcoming meetings when authorized.
Agent runs waiting for input/approval or containing deliverables.
Versioned artifacts needing review.
User feedback and attention overrides.
Output contract
Return no more than three items. Each item contains:
There is deliberately no attention_score field: gates are deterministic and selection belongs to the judgment, so nothing legitimately consumes a numeric score — exposing one invites sorting by a mysterious AI number.
The UI always offers no more than three actions. Typical card:
Update Sarah’s investor email
Sarah raised a new pricing concern, so yesterday’s draft is stale. This supports “Build investor pipeline.” Update draft · Later · Dismiss
Deterministic gates — two separate sets, never conflated
The model's judgment is advisory (there are no numeric scores); deterministic policy alone decides eligibility and interruption. The two gate sets are distinct: notification settings, quiet hours, focus, and frequency budgets never filter the dashboard. The dashboard is the alternative to interruption, not another notification channel — quiet hours emptying the dashboard is a bug.
Recommendation eligibility gates (apply to the dashboard and the shortlist):
Subject still open and unexpired; dedupe key not already active.
Evidence/capture-confidence threshold.
The recommendation has a concrete action.
Interruption eligibility gates (apply only to proactive notifications, on top of eligibility):
Master notifications and per-assistant settings.
Floating-bar snooze and focus state.
User quiet hours.
Global and task-specific frequency budget.
Whether the item can wait for the dashboard/digest.
Default taste:
Dashboard: up to three items, refreshed on meaningful context change or explicit open.
Proactive task interruptions: maximum two per day by default, at least 90 minutes apart.
Explicit user-created due reminders are governed by reminder settings, not this proactive budget.
No notification whose only message is “New task.”
If there is no genuinely useful recommendation, show nothing.
Contextual resurfacing
macOS should generate normalized local context events when authorized:
The person tied to a commitment reappears in chat/email.
The relevant file, document, PR, or app becomes active.
A related meeting approaches.
The user enters an appropriate free-time window.
New conversation evidence changes a workstream assumption.
A dependency becomes unblocked.
A draft becomes stale relative to new evidence.
An agent finishes or requires a decision.
These events trigger re-evaluation, not automatic notification. Coalesce rapid events by workstream and use semantic/materiality checks so tab switching does not produce churn.
No global screen-context stream should be uploaded to support this. Run context matching locally where possible and send only minimized workstream events/provenance allowed by policy.
Versioned artifacts and evolving drafts
Artifacts are first-class workstream outputs. A logical artifact such as investor_email_draft:sarah may have multiple immutable versions:
artifact_id
workstream_id
logical_key
version
supersedes_artifact_id?
kind
uri
content_hash
status = draft | awaiting_review | approved | delivered | superseded
source_run_id?
evidence_event_ids[]
created_at
When a conversation evolves:
Append the new evidence event.
Mark the current draft as potentially stale through a derived evaluation; do not destroy it.
Resume the same workstream agent conversation.
Create a new artifact version citing the evidence that caused the change.
Surface review only if the update is material and action-ready.
Never overwrite a draft in place and never rely on an unbounded chat transcript as the only durable record of why it changed.
Later creates a context/time attention override; it does not lower task value.
User edits are strong wording/specificity feedback.
Completion is positive outcome evidence but must not blindly imply every semantically similar future task is valuable.
Silence and notification dismissal without a reason are weak signals only.
Feedback must be attributable from intervention → candidate/task/workstream → later outcome. Do not log raw private content to analytics; log stable IDs, reason codes, confidence bands, source class, and timing.
This epic ships signal capture only — no online learning mechanism. The attribution chain must be complete from the very first event (you cannot retro-fit signal that was never logged), but the loop that turns signal into behavior change — threshold recalibration, prompt/fixture iteration, legible per-user rules — runs offline afterward in #9360. The behavior descriptions above ("Not mine updates ownership features", etc.) define what the offline iteration must achieve, not an online mechanism to build now.
Target user experience
Dashboard
“What matters now” occupies the primary intelligent position.
Maximum three recommendations.
Focused goals remain visible as durable orientation, not mixed into the recommendation list.
No empty-state filler recommendation.
Goals
Show focused goals first, with an explicit focus-management interaction.
Provide “All goals” for background/paused/history.
Goal detail shows desired outcome, why it matters, success criteria, active threads (workstreams rendered as sections of the goal), meaningful progress events, and optional metric.
Starting work from a goal (“Work on this with Omi”) creates an anchor task and its thread — there is no direct “new thread” management on goal detail (principle 4b).
Do not expose an ontology editor or graph-management UI.
Workstream (thread view — reached through Tasks and Goals, never a top-level surface)
One continuous thread with current-state summary, recent changes, open tasks, artifacts, and agent activity.
Entered by opening a task's thread or a goal's thread section — there is no workstream tab, list, or create-workstream management surface (principle 4b).
Resume rather than restart.
New conversations/files can appear as evidence updates.
Task-specific entry scrolls/scopes the workstream to that task without changing session identity.
Tasks
Keep the fast list, manual CRUD, due dates, recurrence, search, and integrations.
Add a quiet Suggested lane/inbox; no badge inflation or notification per candidate.
Show a concise “why” affordance for Omi-created tasks.
Do not sort the full list solely by personalized relevance. Manual order and due-date structure remain useful; personalization belongs primarily in “What matters now.”
No new durable agent state may be added to UserDefaults, Swift GRDB task rows, or Firestore task-chat documents. Existing local task agent/chat state must migrate toward kernel projections and then be deleted.
Implementation phases
How to read the phases under a compressed build
The build is AI-driven and compressed (~5 days total, macOS-first). The phases below are dependency and review boundaries, not a calendar. Rules:
Each phase lands as its own reviewable PR (or small PR series). Do not deliver the epic as one giant merge — the phases are also the rollback boundaries. But the phases are not a sequence of seven sequential PRs; run them as parallel lanes (below).
Vertical slice first: the scenario 13 golden path end-to-end on macOS. Quiet capture of a commitment → “Work on this with Omi” silently forming the thread → a prepared draft → new evidence producing a cited v2 → What Matters Now resurfacing it. This covers workstream schema + journal, kernel session binding, versioned artifacts, thread-behind-a-task UI, and quiet capture in one loop. It is the dogfood target — it proves both acquisition and compounding value on a real user before the migration finishes. If the slice doesn't feel right in dogfood, stop and fix it before proceeding. (There is no “manually created workstream” concept — creation is only via the three paths in principle 4.)
Parallel lanes, Day 0–5 critical path:
Lane A — slice: Phase 0 fixtures → golden-path slice (the needed parts of Phases 2/3/5) → dogfoodable by end of Day 2.
Lane B — contracts: Phase 1 canonical contract + Candidate lifecycle → Phase 2 remainder (goals migration, association pipeline).
Lane C — policy/UX: Phase 4 feedback UX → Phase 5 full projection → Phase 6 (dogfood-only interruptions).
Lanes merge behind the per-user mode flags. Target: dogfood Days 2–3, beta Day 4, prod Day 5 for the whitelist cohort. The general-population contract cutover may trail Day 5 (see Rollout — two axes).
Ship gates are mechanical go/no-go, in order — the dates are targets; these gates are binding:
Dogfood → beta: ≥2 dogfood days; ≥10 auto-accepted commitments reviewed at ≥80% judged-correct precision; zero deterministic-gate bypasses; scenario-13 E2E green.
Beta → prod: zero reconciliation/data-loss errors in beta; zero interruption-budget violations; no spike in auto-accepted-task deletions.
Dual-write legacy staged_tasks into Candidates in shadow/write modes, migrate active rows idempotently, and reconcile promotion history.
Remove timer-based automatic staged promotion and per-promotion notifications after read cutover.
Ensure default task integrations receive accepted tasks according to one documented policy, regardless of source.
Acceptance:
Every source round-trips typed fields without local preservation hacks.
Notifications off does not stop candidate discovery.
Task candidate acceptance creates exactly one task; workstream candidate acceptance creates exactly one workstream plus one anchor task; retrying either resolution produces no additional objects.
Accepted objects preserve the envelope's evidence and goal link.
Migrate current task→goal links from desktop/backend data where valid. Mobile-only preference links are imported once when available, then deleted from preferences.
Create workstreams only from explicit user action, accepted agent proposal, consolidation-proposed recurrence (see Workstream association → Cold start), or migration of an existing task with durable agent history—not for every task.
Introduce append-only meaningful progress events and optional metric updates.
Implement the workstream association pipeline (retrieval index over workstream summaries + LLM adjudication) against the golden association fixtures, gated to the canonical-memory cohort.
Acceptance:
Creating a sixth goal never deactivates another goal.
Exactly the configured number of goals can be focused; overflow requires an explicit choice.
Deleting/archiving a goal does not delete tasks, workstreams, artifacts, or evidence; it requires an explicit relationship disposition.
Association fixture suite passes; entity overlap alone never associates evidence to a workstream.
Phase 3 — Persistent workstream agent continuity
Goal: Agents resume ongoing work with current context and versioned outputs.
Deliver:
Add the workstream surface reference to the kernel and deterministic session resolution by workstream ID.
Add a local workstream binding/projection table only if the existing surface_sessions mapping cannot express it; prefer extending the existing mapping.
Change task chat/investigate/execute entry points to resolve the workstream conversation.
Migrate resumable task-chat histories and artifacts into workstream sessions. Preserve legacy references only for a bounded compatibility window, then burn them.
Build workstream context packets from current summary, selected recent events, task state, artifact heads, and explicit provenance. Never replay an unbounded transcript.
Append agent-produced summaries, decisions, artifact versions, and Candidates back to the workstream product domain through auditable delivery records.
Reuse the existing kernel candidates, action queue, dispatches, grants, artifacts, and attention overrides. Do not build a second coordinator.
Add continuation checkpoints so another device/runtime can reconstruct product context without claiming the original local agent session.
Acceptance:
Opening two tasks in one workstream resumes one conversation.
A new conversation event changes an existing draft by producing a cited new version, not overwriting history.
App restart resumes via kernel authority, not Swift/UserDefaults state.
A second device can show current state/artifact descriptors and establish a new local continuation without false run status.
Agent task mutations appear as candidates unless policy proves an explicit command.
Required deletion:
Per-task session identity as the canonical continuity boundary.
Legacy tmux TaskAgent lifecycle once all execution uses kernel runs.
Swift-persisted agent truth duplicated from the kernel.
Phase 4 — Quiet Suggested UX and three-choice feedback
Goal: Make broad capture trustworthy without making it noisy.
“Later” hides the intervention but preserves task value.
Phase 5 — “What matters now” projection
Goal: Make Omi’s intelligence visible through a small number of high-value next moves.
Deliver:
Add the evaluation service per the Evaluations section: deterministic fact calculation, deterministic shortlist (filter, never rank), one holistic model judgment, auditable decision record (no raw reasoning text). No component-score contract.
Combine tasks, workstreams, candidates, artifacts, decisions, and kernel open loops into one expiring recommendation projection.
Render up to three dashboard recommendations with why-now and concrete next actions.
Make recommendation actions open/resume the correct workstream and agent context.
Add empty-result behavior: show nothing rather than weak filler.
Add explanation/debug tooling for internal QA reading the decision record (shortlist, facts snapshot, versions, reason codes), gates, evidence refs, and dedupe decisions without exposing raw private content in analytics.
Acceptance:
Personalized evaluation changes recommendation selection, not the full-list canonical order.
Every recommendation has evidence, a concrete action, expiry, and dedupe key.
A workstream/agent open loop can outrank a task when user action is required.
Reopening the dashboard does not reshuffle without a material input change.
Golden ranking fixtures pass; no code outside debug tooling parses the decision record's summary or reason codes.
Phase 6 — Contextual resurfacing and proactive preparation
Goal: Use macOS context to surface or prepare work at genuinely better moments.
Deliver:
Local matchers for relevant person/app/window/document/meeting/free-time/dependency events.
Materiality/coalescing logic by workstream.
Re-evaluation hooks that update “What matters now” without automatically interrupting.
Proactive agent preparation for reversible artifacts when execution readiness is high and policy allows it.
Deterministic notification gates, daily budget, dedupe, quiet hours, and user controls.
Notification content with why-now and action—not “New task.”
Proactive interruptions ship dogfood/opt-in only. They stay off by default for beta/prod cohorts until dashboard metrics demonstrate recommendation usefulness. The daily budget is a ceiling, not permission to send — zero interruptions on a day with nothing worth interrupting for is correct behavior.
Acceptance:
Notifications off still permits quiet local capture and dashboard recommendations.
Beta/prod users receive no proactive task interruptions until the opt-in/metrics gate is explicitly lifted.
No proactive task notification bypasses global settings or budget.
Reopening a relevant Slack thread can surface the existing workstream/draft rather than create a duplicate task.
Rapid app/window switching produces at most one coalesced re-evaluation.
Prepared drafts remain local/versioned until user review.
Phase 7 — Backend tools, integrations alignment, and legacy burn-down
Goal: Stable universal contract and no surviving legacy paths. (Mobile/web/cross-surface UI moved to #9359.)
Deliver:
Chat/voice/MCP tools for goals, workstreams, Candidates, feedback, and “What matters now,” generated from one manifest/contract.
Import/export/integration behavior aligned with canonical task acceptance.
Reconciliation and deletion of legacy staged tasks, local-only goal links, obsolete score fields, old task-chat session stores, and migration flags — gated on the universal contract migration (rollout axis 1) reaching general-population read, which may trail the 5-day whitelist ship.
Public developer documentation for the stable domain and tool behavior.
Acceptance:
A task created through chat/MCP tools carries the same evidence/relationships as one created on desktop.
Surface capability gaps are explicit; no surface fabricates agent state.
Grep-based checks prove legacy writers and duplicate authorities are gone.
Universal contract migration (everyone, eventually). All task/goal writers — every surface, every user — move onto the canonical write contract through off | shadow | write | read. Old clients consume compatibility projections. This axis may legitimately trail the 5-day clock: general-population read cutover happens when reconciliation is clean, and legacy-writer deletion (Phase 7, epic DoD) is gated on this axis completing — it is an epic-completion criterion, not a Day-5 one. Do not force the general population's cutover inside the 5-day window to satisfy a deletion clause; mobile prod users' tasks/goals are the widest blast radius in this epic.
Cohort-gated intelligence (memory whitelist, the 5-day clock). Workstream association, evaluation/ranking, What Matters Now, thread UI, and quiet-capture auto-accept enable only for the canonical-memory whitelist cohort on macOS.
Without this split the epic contradicts itself: off-mode users on legacy writers forever versus Phase 7 deleting those writers. The mode table below governs axis 1; the whitelist governs axis 2.
Cohort and ship gates
Cohort for intelligence: the canonical-memory whitelist (macOS beta). Do not enroll users outside the memory cohort — workstream association depends on canonical memory.
Ship gates (mechanical, binding — see Implementation phases for the go/no-go criteria): dogfood → beta → prod, ~5 days total for the whitelist cohort. Dates are targets; gates are binding.
New candidate/evaluation/workstream logic runs without product-visible mutations or interruptions.
write
Legacy reads remain authoritative; canonical sidecar writes and reconciliation run.
read
New domain is authoritative for enrolled users; compatibility projections serve old clients.
Requirements:
Every write carries an idempotency key and account generation.
Migration is resumable and reports per-user counts/checkpoints.
Compatibility projections must preserve old mobile clients during rollout.
Rollback from read uses reconciled compatibility projections; it must not resurrect rejected candidates, lose accepted tasks, or detach goal/workstream links.
No notification experiment runs in shadow mode.
Rollout gates include metadata round-trip parity, candidate precision, interruption budget, agent-continuity E2E, and reconciliation health.
Metrics
North star
User-validated, Omi-assisted advances per active week. An advance is one of:
A task completed or materially advanced.
A draft/artifact approved, revised, or delivered.
A blocking decision resolved.
A workstream materially advanced by user-reviewed agent work.
An agent run resumed producing output the user acted on.
"User-validated" is mechanical, not judged — and validation is not the advance. "Do now", candidate acceptance, and edit-and-keep validate relevance and create the attribution link; the advance itself counts only on a downstream outcome: task completed, output applied/delivered, decision resolved, or artifact approved. Automatic summary updates, untouched auto-accepted tasks, and un-acted-on "Do now" taps never count as advances — Omi does not grade its own homework.
Efficiency guardrail
Proactive interruptions per advance. This is a guardrail, not the north star — a ratio alone is degenerate (suppressing all interruptions makes it look perfect while creating no value).
Required guardrails
Proactive interruptions per active day.
Interruption dismiss rate and reason.
Task notification disable/snooze rate.
Candidate acceptance/edit/rejection rate by source and confidence band.
Auto-accepted task deletion within 24 hours.
“Not mine” rate by source modality.
Time from recommendation to meaningful advance.
Duplicate creation and stale-draft rates.
Workstream resume rate versus new-thread creation.
Agent artifact approval/delivery rate.
Percentage of days where “What matters now” correctly returns fewer than three items.
Do not treat task count, extraction count, recommendation impressions, or notification clicks as success metrics.
Required end-to-end scenarios
Quiet commitment: User promises Sarah in Slack to send a budget Friday. Omi silently creates/accepts the task with evidence. No notification fires. It appears in “What matters now” when urgency/context warrants it.
Unaddressed request: A direct request arrives without acceptance. Omi creates a Suggested candidate, not an active task or notification.
Ownership correction: User dismisses with Not mine. In this epic: the exact candidate/evidence is suppressed, the equivalent intervention is deduped, and the signal is persisted with full attribution. (Making similar public-channel requests less likely to be assigned — without suppressing direct mentions — is Follow-up: Offline feedback-learning iteration and legible per-user rules #9360's acceptance criterion, powered by this signal.)
Already handled: User selects Already handled. Omi resolves the candidate or proposes task completion and does not re-extract the same evidence.
Evolving email: A workstream contains an investor email draft. A later conversation changes pricing context. The same workstream agent resumes and produces draft v2 citing the new event; v1 remains inspectable.
Shared workstream continuity: Two tasks under one workstream open one canonical agent conversation and shared artifacts.
Cross-device event: User adds a note on mobile. Desktop resumes the workstream with that event in a minimized context packet. (Backend support in this epic; the mobile UI to append the note ships in Follow-up: Tasks/Goals/Workstreams on mobile, web, and non-macOS surfaces #9359 — verify with an API-level event append until then.)
Attention restraint: Five candidates are captured in an hour. None produces “New task” notifications. At most one high-value contextual intervention appears if all gates pass.
No relevance theater: A low-confidence, weakly actionable item cannot rank merely because it matches a focused goal.
Goal focus: User creates more than five goals. All persist; only explicitly chosen goals are focused.
Agent caution: Agent prepares a reply but cannot send it without an approved dispatch/grant.
Privacy: Screen evidence remains local; backend receives only allowed minimized summaries and references.
Golden path (the dogfood script — composes 1 + 5): User promises Sarah a budget in Slack. Omi silently captures the task with evidence (no notification). User opens it and taps “Work on this with Omi” — a thread silently forms and Omi prepares a draft. Days later a conversation changes the pricing context; the same thread resumes and produces draft v2 citing the new evidence, v1 stays inspectable. “What matters now” resurfaces the stale-draft review at a sensible moment. This single loop demonstrates both day-1 acquisition value and compounding value, and is the canonical named-bundle E2E.
Test and verification requirements
Every behavior change follows repository Definition of Done and adds the regression/core-path tests that would have caught failure.
At minimum:
Backend schema/database/router unit tests and hermetic lifecycle contracts.
OpenAPI runner plus regenerated Swift/Dart contract verification.
Import-side-effect and async-blocker scans for backend changes.
Desktop kernel tests for workstream session resolution, candidates, action queue, artifacts, context packets, attention overrides, and restart reconciliation.
Desktop Swift tests for projections and UI state only—not duplicate lifecycle logic.
Named-bundle desktop E2E with omi-ctl/agent tooling covering quiet capture, workstream resume, evolving artifact, What Matters Now, feedback, and notification gates.
A cross-modality evaluation suite run against screen and transcript extraction.
The golden association and golden ranking fixture suites in CI, run hermetically against recorded/stubbed judgments per repo testing rules; live-model quality evals in a separate versioned evaluation workflow (not CI), gating prompt/model changes.
A round-trip test that fails if any canonical task/workstream/goal field disappears after create → list → update → desktop cache → mobile (Dart) decode.
No phase is complete based only on compilation, prompt snapshots, or unit tests. Exercise the real user-facing path and retain evidence.
Explicit non-goals
Building a general project-management system with boards, dependencies, and arbitrary graphs.
Showing unlimited goals on the dashboard.
Treating broad interests/profile facts as goals.
Sorting the entire task list by a mysterious AI number.
Uploading raw screen history to power contextual resurfacing.
Letting an LLM alone decide whether to interrupt.
Autonomous external sending or consequential writes without policy approval.
Syncing local adapter-native agent lifecycle as canonical backend truth.
Creating a new agent framework separate from the existing kernel/coordinator.
Keeping both staged_tasks and Candidates as permanent active systems.
Preserving one independent long-running thread per task when tasks share a workstream.
Using notification clicks, task count, or extraction volume as the optimization target.
A user-facing “Workstreams” tab, list, or management surface (principle 4b).
A typed multi-component evaluation score contract that other systems compute against (Evaluations section).
Goals may be numerous; focused goals are few. Do not restore “adding one silently deactivates the oldest.”
Workstream is the continuity boundary. Task is not the durable agent-session boundary.
Backend owns product state; kernel owns local execution truth. Do not create another authority.
Capture and interruption are separate. Notifications off does not disable discovery.
What Matters Now is derived and limited to three. Do not persist it as task order.
Feedback has three visible dismiss reasons. Do not grow a survey.
Artifacts are versioned, not overwritten. New evidence creates a new cited version.
Agents propose mutations by default. Explicit user intent and policy are the only direct-mutation shortcut.
No “New task” interruption. The interruption must explain why now and offer a useful action.
Legacy paths are deleted after migration. A feature flag is a rollout tool, not permanent architecture.
The UI vocabulary is Goals and Tasks. Workstream stays in the domain model but is never a user-facing managed noun, tab, or list. Do not merge goal and workstream in the domain model either — they are different concepts (outcome vs. body of work).
Workstream evidence reuses canonical memory provenance. One provenance graph; workstreams are Workflow, not a memory tier, and never duplicate memory/conversation content. No association path on legacy memory.
Evaluation is one holistic judgment with an auditable decision record. Facts in, deterministic shortlist (filter, never rank), gates around, judgment in the middle, decision record out. Never store raw model reasoning text; never resurrect a typed multi-component score contract; quality is enforced by golden fixtures, not component assertions.
Interruption is earned. Proactive interruptions are dogfood/opt-in until dashboard metrics demonstrate usefulness; the daily budget is a ceiling, not permission.
Workstream proposals ride the universal candidate lifecycle.subject_kind = workstream on the same candidate model — never a parallel proposal system, and the memory system never writes workflow objects.
Open product decisions for iteration
These are intentionally narrow; they do not reopen the architecture above.
User-facing nameResolved: no user-facing workstream noun at all (decision 11). “Workstream” stays internal/API-only; if a label is unavoidable in a thread view, use “Thread.”
Focused-goal default: prescription is five maximum, while dashboard may visually feature only three. Validate with real usage before changing either number.
Proactive preparation budget: determine which reversible artifact types may be prepared automatically and what local compute/cost budget applies.
Cross-device continuation depth: v1 syncs workstream journal/checkpoints and artifact descriptors, not adapter transcripts. Expand only with a separate privacy and authority design.
Definition of done for the epic
The epic is complete when:
All task sources use one canonical contract and candidate policy.
Epic: Rebuild Omi Tasks around quiet capture, focused goals, persistent workstreams, and contextual action
Summary
Omi should not compete with ordinary task managers by extracting more todos. Omi should use what it knows about the user to identify meaningful commitments, preserve the context around ongoing outcomes, and help move the right work forward at the right moment without becoming noisy.
This epic replaces the current collection of partially connected task, goal, staged-task, notification, and task-chat behaviors with one product model:
The intended experience is calm and opinionated:
This is a prescriptive implementation plan. Future implementers MUST preserve the product principles and sources-of-truth decisions below. If a phase must be split, split the delivery—not the invariants.
Scope and rollout decisions (locked for this epic)
memory_items, INV-MEM-1/2/3) — never against legacy memory reads. Ship to the memory-whitelist cohort; do not build a legacy-memory compatibility path that would immediately be deleted.off | shadow | write | readmachinery below still exists per user — it is the safety mechanism, not a calendar.Product thesis
The user does not need Omi to produce a longer list. The user needs Omi to reduce cognitive load and make meaningful progress.
The north-star behavior is:
We are optimizing for user-validated, Omi-assisted advances per active week — value actually created — with proactive interruptions per advance as the efficiency guardrail. Not tasks extracted, notification clicks, or list size. A ratio alone is not the north star: suppressing all interruptions makes a ratio look perfect while the product does nothing.
Taste and non-negotiable product principles
1. Quiet capture; selective interruption
Discovery and notification MUST be separate settings and separate decisions.
The current coupling in
TaskAssistant.isEnabledandTaskPromotionServicemust be deleted: task analysis is gated on task notifications, while promoted tasks bypass frequency throttling.2. “What matters now” is not another task list
The primary intelligent surface ranks next best moves, not rows. It may select a task, a draft needing review, a decision, a blocked agent run, or a workstream that changed materially.
It shows at most three items. Each item must answer:
The full Tasks page remains the control surface and archive. It must not become the primary expression of Omi’s intelligence.
3. Goals are durable outcomes, not interests and not an arbitrary top-three list
Goals represent longer-lived outcomes the user cares about achieving. Examples:
Goals are not generic interests such as “AI” or “health”; those belong in the user profile. Goals are also not individual next actions; those are tasks.
Users may have many goals. Only a small number—default maximum five—may be focused at once. Adding a sixth goal MUST NOT silently deactivate the oldest goal. Background, paused, achieved, and abandoned goals remain available as context and history.
4. Workstreams are the missing durable middle
A workstream is an evolving body of work that accumulates context over time. It can belong to a goal, but a lightweight workstream may exist without one.
Examples:
A workstream owns:
Tasks do not own agent continuity. Task chat becomes a view into the task’s workstream. If a plain task has no workstream, the first investigation/execution may explicitly promote it into a workstream; do not silently create hundreds of empty workstreams during extraction.
Workstreams come into existence three ways, and only three — and none of them is a user-facing “create workstream” action:
subject_kind = workstream), rendered as an ordinary Suggested card. Accepting it creates the workstream plus its first anchor task in one transactional, idempotent resolution.4b. Noun budget: the UI vocabulary is Goals and Tasks — nothing else
Goal and Workstream are different concepts and must not be merged in the domain model (a goal is a durable outcome; a workstream is a body of work with continuity; lightweight workstreams may have no goal). But the user-facing vocabulary has exactly two managed nouns: Goals and Tasks.
5. Agents prepare continuously but mutate cautiously
Within a workstream, agents may autonomously:
Agents MUST NOT silently:
External writes and consequential mutations continue through coordinator dispatch/grant policy. Explicit, unambiguous user commands may use the existing policy-authorized direct-mutation path.
6. Feedback stays tiny
At any decision step the UI shows no more than three choices.
The standard recommendation actions are:
After Dismiss, an optional second step shows exactly three reason chips:
Dismiss-without-reason remains valid. Silence is not negative feedback. Do not add a longer taxonomy to the UI; richer internal outcomes must be derived from these three reasons and observed state transitions.
Current-state problems this epic must remove
The implementation is not starting from zero, but the existing parts disagree about authority and lifecycle.
TaskPrioritizationServiceranks only local staged tasks. The visible Tasks page then sorts action items by due date and creation time.action_items; manual/chat/integration creation follows other paths.goal_id, but the current backend action-item update contract does not accept it.Every replaced path must be deleted after migration. Do not preserve legacy extraction/promotion behavior as a permanent fallback.
Canonical product model
Goal
Canonical backend-owned product state:
Rules:
Workstream
Canonical backend-owned product state:
Related collections:
Workstream events are append-only and include:
EvidenceRefis one typed shape used everywhere — journal events, candidates, artifacts, and decision records all carry the same type. Do not invent per-surface ref variants:Scope rules: a
device_localref withoutdevice_idis invalid everywhere. Backend/canonical stores may persistdevice_localrefs (withdevice_id) but consumers on other devices must degrade gracefully — render the event summary, mark the evidence as available on<device>, and never fabricate or block on it.Do not synchronize raw screenshots into the backend workstream journal. Persist minimized summaries and evidence references under existing privacy policy. Local screen evidence remains local unless the user explicitly authorizes broader sharing.
Evidence references reuse the canonical memory provenance vocabulary — no parallel memory system.
evidence_refs[]point at Conversations and canonical memory items via the typedEvidenceRefabove, which subsumes the memory domain model'sevidence[].source_idpattern (docs/memory/domain_model.md). A workstream journal entry that summarizes a conversation cites the Conversation; one that leans on a durable fact cites the memory item. Workstreams are Workflow in the memory glossary's terms — they are not a memory tier, never appear in Memories UI, and must not duplicate conversation or memory content into their own store (summaries + refs only). This keeps one provenance graph across memory and workflow (INV-MEM-1 vocabulary applies; do not invent new tier-like concepts).Task
users/{uid}/action_items/{task_id}remains the compatibility collection during rollout, but its canonical schema is expanded:Rules:
workstream.goal_idandtask.goal_idmust agree. Enforce this server-side.Candidate (universal review lifecycle)
Replace
staged_taskswith one universal Candidate lifecycle — the internal name is "Candidate", not "task candidate". The payload is a discriminated union onsubject_kind: exactly one typed payload is present, so implementations cannot drift on a genericproposed_changeblob:Envelope vs. payload authority: the envelope owns capture metadata (
goal_id,evidence_refs, confidences,source_surface); the payload owns only the proposed object's own fields. No field may appear in both.Rules:
subject_kind = workstream, from accepted agent proposals or consolidation recurrence) use this same lifecycle and render as ordinary Suggested cards; accepting one creates the workstream plus its first anchor task in one transactional, idempotent resolution — never two independent writes.Evaluations and attention decisions
The evaluation architecture is facts in, gates around, one judgment in the middle, trace out. Do not build a decomposed multi-component scoring formula that other code computes against — that is explicitly rejected. The model judges holistically; deterministic code supplies inputs and enforces policy.
Facts (deterministic inputs, computed by code, verifiable):
Facts are inputs to the judgment, never model outputs. They do not decay as models improve.
Gates (deterministic policy, never model-shaped): the attention gates in the “What matters now” section below. Budgets, quiet hours, dedupe, and thresholds are code.
Shortlist (deterministic, before any model call): a deterministic eligibility stage narrows the candidate set to roughly 10–20 items using facts only — open/unexpired, passing the recommendation eligibility gates (never the interruption gates — see the two gate sets below), recent material activity or due-window. The shortlist filters, never ranks; the moment it scores, the rejected component contract has been rebuilt upstream.
Judgment (one holistic model call): given the shortlist, the facts, the user's feedback history, and current context, the model selects ≤3 items and writes headline / why-now / recommended action. There are no separately-computed component scores (
urgency,personal_value,goal_alignment, etc.) persisted as a typed contract. The public contract is the output (recommendation card shape, dedupe key, expiry) plus the gates — not the model's internal reasoning.Decision record (auditable, versioned, for debugging and attribution only). Do not store raw model reasoning text — chain-of-thought is unstable across model versions and is exactly the raw private content this epic forbids logging:
The decision record powers QA/debug tooling and feedback attribution. No system outside debug tooling may parse or branch on
decision_summary/reason_codes— if the codes grow a consumer, the component-score taxonomy has returned through the back door. When a better model ships, swap the judgment and rerun the golden fixtures — no schema migration.Testing: judgment quality is verified by golden ranking fixtures ("given this user state, these items must surface / must not surface"), not component-level score assertions. Fixture runs in CI are hermetic (recorded/stubbed judgments per repo testing rules); live-model quality evals run in a separate versioned evaluation workflow, not CI.
What matters nowis a derived projection over canonical goals/workstreams/tasks, agent open loops, artifacts, context, and these evaluations. It is not persisted as task order and is never a source of truth.Workstream agent binding
Execution truth remains in the desktop TypeScript runtime kernel and
omi-agentd.sqlite3:surfaceKind=workstream,externalRefKind=workstream,externalRefId=<workstream_id>.(owner, device/runtime, workstream_id).The backend stores product workstream state, event summaries, and artifact descriptors/checkpoints. It does not become authoritative for local run success/failure. A second device reconstructs context from the canonical workstream journal and continuation checkpoint, then establishes its own local runtime binding.
The existing kernel
desktop_task_candidatestable remains the auditable local proposal/outbox for agent-originated mutations; it is not a second product review authority. Delivery creates or resolves the backend canonical task candidate idempotently, records the backend candidate ID/receipt in kernel events or artifact-delivery metadata, and projects the canonical resolution back into the local action queue. Do not leave independent “pending” states in both stores.Task chat behavior:
Capture and promotion policy
Desktop screen extraction and backend conversation extraction MUST consume one shared policy specification and shared eval fixtures. Prompts may differ by modality, but commitment semantics and expected outcomes may not.
Workstream association (the hard problem — do not hand-wave it)
“New evidence updates the workstream journal” hides the hardest ML problem in this epic: given new evidence, which existing workstream (if any) is it about? If association precision is poor, journals fill with noise and current-state summaries stop being trustworthy; if it is too conservative, workstreams go stale. Treat association quality as a first-class deliverable with its own eval fixtures, equal in rigor to the capture fixtures.
Memory clusters by entity and fact similarity; workstreams cluster by intent and outcome. “This conversation mentions Sarah” does not mean “this belongs to the investor-outreach-to-Sarah workstream” — the association step must discriminate intent, not just entity overlap.
Prescribed pipeline (reuse the canonical memory system; only the adjudicator is new)
objective+current_state_summaryin a derived, rebuildable index (authority table: search/vector indexes are never canonical). Retrieval follows the INV-MEM-2 shape — vector hits are candidate workstream IDs only, hydrated against authoritative workstream records before use; fail closed.Cold start
Workstream creation proposals come from memory consolidation recurrence (see principle 4): consolidation emits recurrence evidence when the same unresolved open loop repeats across multiple days, and the workflow domain turns it into a
subject_kind=workstreamcandidate — the memory system never writes workflow objects. One-off mentions never qualify. This is deliberate — association has a small candidate set to adjudicate against precisely because workstreams are few and meaningful.Acceptance
“What matters now” behavior
Inputs
Output contract
Return no more than three items. Each item contains:
There is deliberately no
attention_scorefield: gates are deterministic and selection belongs to the judgment, so nothing legitimately consumes a numeric score — exposing one invites sorting by a mysterious AI number.The UI always offers no more than three actions. Typical card:
Deterministic gates — two separate sets, never conflated
The model's judgment is advisory (there are no numeric scores); deterministic policy alone decides eligibility and interruption. The two gate sets are distinct: notification settings, quiet hours, focus, and frequency budgets never filter the dashboard. The dashboard is the alternative to interruption, not another notification channel — quiet hours emptying the dashboard is a bug.
Recommendation eligibility gates (apply to the dashboard and the shortlist):
Interruption eligibility gates (apply only to proactive notifications, on top of eligibility):
Default taste:
Contextual resurfacing
macOS should generate normalized local context events when authorized:
These events trigger re-evaluation, not automatic notification. Coalesce rapid events by workstream and use semantic/materiality checks so tab switching does not produce churn.
No global screen-context stream should be uploaded to support this. Run context matching locally where possible and send only minimized workstream events/provenance allowed by policy.
Versioned artifacts and evolving drafts
Artifacts are first-class workstream outputs. A logical artifact such as
investor_email_draft:sarahmay have multiple immutable versions:When a conversation evolves:
Never overwrite a draft in place and never rely on an unbounded chat transcript as the only durable record of why it changed.
Feedback and learning
Canonical feedback event:
Behavior:
Feedback must be attributable from intervention → candidate/task/workstream → later outcome. Do not log raw private content to analytics; log stable IDs, reason codes, confidence bands, source class, and timing.
This epic ships signal capture only — no online learning mechanism. The attribution chain must be complete from the very first event (you cannot retro-fit signal that was never logged), but the loop that turns signal into behavior change — threshold recalibration, prompt/fixture iteration, legible per-user rules — runs offline afterward in #9360. The behavior descriptions above ("Not mine updates ownership features", etc.) define what the offline iteration must achieve, not an online mechanism to build now.
Target user experience
Dashboard
Goals
Workstream (thread view — reached through Tasks and Goals, never a top-level surface)
Tasks
Mobile — out of scope for this epic (see #9359)
Authority boundaries
omi-agentd.sqlite3No new durable agent state may be added to UserDefaults, Swift GRDB task rows, or Firestore task-chat documents. Existing local task agent/chat state must migrate toward kernel projections and then be deleted.
Implementation phases
How to read the phases under a compressed build
The build is AI-driven and compressed (~5 days total, macOS-first). The phases below are dependency and review boundaries, not a calendar. Rules:
Phase 0 — Contract fixtures, measurement, and safety rails
Goal: Make current behavior and target semantics testable before moving data.
Deliver:
off | shadow | write | readsemantics per user.Acceptance:
Phase 1 — Canonical task contract and universal candidate lifecycle
Goal: One backend contract for every surface; quiet candidates replace staged tasks.
Deliver:
candidatesendpoints (discriminatedsubject_kindpayloads per the Candidate model) and transactional accept/reject/expire resolution.staged_tasksinto Candidates in shadow/write modes, migrate active rows idempotently, and reconcile promotion history.Acceptance:
staged_taskshas no live writer after cutover.Required deletion:
TaskPromotionServicetimer behavior.Phase 2 — Refactor goals and add canonical workstreams
Goal: Establish durable outcomes and the missing operational middle.
Deliver:
Acceptance:
Phase 3 — Persistent workstream agent continuity
Goal: Agents resume ongoing work with current context and versioned outputs.
Deliver:
surface_sessionsmapping cannot express it; prefer extending the existing mapping.Acceptance:
Required deletion:
Phase 4 — Quiet Suggested UX and three-choice feedback
Goal: Make broad capture trustworthy without making it noisy.
Deliver:
Acceptance:
Phase 5 — “What matters now” projection
Goal: Make Omi’s intelligence visible through a small number of high-value next moves.
Deliver:
Acceptance:
Phase 6 — Contextual resurfacing and proactive preparation
Goal: Use macOS context to surface or prepare work at genuinely better moments.
Deliver:
Acceptance:
Phase 7 — Backend tools, integrations alignment, and legacy burn-down
Goal: Stable universal contract and no surviving legacy paths. (Mobile/web/cross-surface UI moved to #9359.)
Deliver:
read, which may trail the 5-day whitelist ship.Acceptance:
Rollout and migration
Two rollout axes — do not conflate them
off | shadow | write | read. Old clients consume compatibility projections. This axis may legitimately trail the 5-day clock: general-populationreadcutover happens when reconciliation is clean, and legacy-writer deletion (Phase 7, epic DoD) is gated on this axis completing — it is an epic-completion criterion, not a Day-5 one. Do not force the general population's cutover inside the 5-day window to satisfy a deletion clause; mobile prod users' tasks/goals are the widest blast radius in this epic.Without this split the epic contradicts itself:
off-mode users on legacy writers forever versus Phase 7 deleting those writers. The mode table below governs axis 1; the whitelist governs axis 2.Cohort and ship gates
Per-user modes
Use per-user modes:
offshadowwritereadRequirements:
readuses reconciled compatibility projections; it must not resurrect rejected candidates, lose accepted tasks, or detach goal/workstream links.Metrics
North star
User-validated, Omi-assisted advances per active week. An advance is one of:
"User-validated" is mechanical, not judged — and validation is not the advance. "Do now", candidate acceptance, and edit-and-keep validate relevance and create the attribution link; the advance itself counts only on a downstream outcome: task completed, output applied/delivered, decision resolved, or artifact approved. Automatic summary updates, untouched auto-accepted tasks, and un-acted-on "Do now" taps never count as advances — Omi does not grade its own homework.
Efficiency guardrail
Proactive interruptions per advance. This is a guardrail, not the north star — a ratio alone is degenerate (suppressing all interruptions makes it look perfect while creating no value).
Required guardrails
Do not treat task count, extraction count, recommendation impressions, or notification clicks as success metrics.
Required end-to-end scenarios
Test and verification requirements
Every behavior change follows repository Definition of Done and adds the regression/core-path tests that would have caught failure.
At minimum:
omi-ctl/agent tooling covering quiet capture, workstream resume, evolving artifact, What Matters Now, feedback, and notification gates.No phase is complete based only on compilation, prompt snapshots, or unit tests. Exercise the real user-facing path and retain evidence.
Explicit non-goals
staged_tasksand Candidates as permanent active systems.Decisions future agents must not casually reopen
subject_kind = workstreamon the same candidate model — never a parallel proposal system, and the memory system never writes workflow objects.Open product decisions for iteration
These are intentionally narrow; they do not reopen the architecture above.
User-facing nameResolved: no user-facing workstream noun at all (decision 11). “Workstream” stays internal/API-only; if a label is unavoidable in a thread view, use “Thread.”Definition of done for the epic
The epic is complete when:
Follow-up issues (dependencies of this epic, not scope)
readmode + macOS beta ship