Today (chore surface) — requirements
Epic. MVP-1 requirements breakdown for the Today goal (see the feature architecture). Each FR is sized to become one or a few user stories. Much of this surface is already built by the P1/P2 domain-gaps work — statuses reflect that.
| Type | Functional |
| Layer (build approach) | Frontend — design_system atoms + app bloc/page + flow-test |
| RICE | R 10 × I 3 × C 80% / E 3 = 8.0 · Tier MVP-1 |
| KPI (summary) | Weekly engaged completion — see Success criteria |
| Traces to | feature today-chores · C4 component (TodayChoresBloc, TodayChoreRow) |
| Depends on | Personas / authz · Money & Envelopes (effectiveTokens) · Offline sync · Analytics |
Success criteria (definitive KPI)
Success = ≥ 60% of activated households record a chore_completed on ≥ 4
separate days in a week, sustained across weeks 2–4 after activation.
- Metric: distinct active days/week with ≥ 1 approved completion, per household.
- Target: ≥ 60% of activated households reach ≥ 4 days/week.
- Window: sustained across weeks 2–4 post-activation (activation = the household's first approved completion).
- Why this bar: it is the household-level expression of the north-star WAEH; 4 days/week is where the chore loop reads as a habit, not a novelty.
- Guardrail (token-fade): median tokens-per-completion should trend down over 8 weeks without completion frequency falling — the intrinsic-motivation thesis. A frequency drop as tokens fall is a regression, not success.
- Baseline: no install base yet — treat 60% / 4-days as the launch hypothesis, confirm with the first cohort, then re-baseline from wk-2 data.
Analytics — events to record
All member references are opaque/hashed; no minor PII (see COPPA). Emitted through the consent-gated analytics substrate.
| Event | When | Key properties | Feeds |
|---|---|---|---|
today_viewed | Today tab opened | grouping (by_kid|by_room), assignedCount | engagement denominator (active days) |
chore_completed | completion approved | choreId, kind, effectiveTokens, hadSteps, memberRef | primary KPI → WAEH |
chore_claimed | bounty claimed | choreId, maxPerDay, memberRef | bounty engagement |
step_checked | subtask toggled | choreId, stepIndex | step-breakdown adoption |
completion_submitted | sent to an approval gate | choreId, hasPhoto=false (MVP-1) | approval funnel |
The KPI is only measurable once
today_viewed(denominator) and the approvedchore_completed(numerator) are both instrumented — these two ship with the surface, not after.
Scope
Today is the primary act surface: each member's chores due today, grouped and filtered to them, with a one-tap completion/submission flow. MVP-1 delivers the assigned-only list, per-member step rendering, the live token value, by-room grouping, and bounty claiming. Photo submissions and AI recommendations are not MVP-1 here.
Functional requirements
FR-TODAY-1 — Member sees only their assigned chores
Priority: P1 · Status: ✅ built (3c6f8fc)
Statement. As a member, I see only the chores assigned to me (or unassigned =
all eligible by minAge) so my list is mine, not the whole household's.
Acceptance
- Given a chore with
assignedMemberIds = [me]When I open Today Then it appears for me and not for unassigned members. - Given a chore with empty
assignedMemberIdsWhen Today loads Then it appears for every age-eligible member. - Resolution uses
assignedMemberIdsUnion; anchored by the Today assignment-filter flow test.
FR-TODAY-2 — Watch-only members never appear on the act surface
Priority: P1 · Status: ✅ built (37fc2dc SDK + 3c6f8fc)
Statement. Watch-only members (tracked for goals, not chores) are excluded from
Today and assignment pickers, so they are never asked to act.
Acceptance — Given watchOnly = true When Today loads Then no completion row, and absent from assignableMembers().
FR-TODAY-3 — Per-member resolved steps render with check-off
Priority: P1 · Status: ✅ built (3c6f8fc)
Statement. As a member, a chore shows my resolved subtasks (stepsForMember).
Acceptance — Given stepsPerMember[me] When it renders under me Then my override steps show; else the chore's default subtasks. Honors the stepBreakdown flag.
FR-TODAY-4 — Token pill shows the effective value
Priority: P1 · Status: ✅ built (70808ae, P2-E)
Statement. The token pill shows effectiveTokens(now) (incl. active temp bonus), not raw tokenValue.
Acceptance — Given an active tempBonus When Today renders Then the pill shows the boosted amount (today_token_pill_effective_test.dart).
FR-TODAY-5 — By-room grouping toggle
Priority: P2 · Status: ✅ built (3c6f8fc)
Acceptance — Given rooms with assignees When I switch to "By room" Then chores group by room and respect per-room assignees.
FR-TODAY-6 — Bounty claim, incl. multi-per-day repeat-claim
Priority: P2 · Status: ✅ built (bb25ac9, P2-H)
Acceptance — Given a multiPerDay bounty with maxPerDay = 3 and 1 approved claim When the pool refreshes Then it is claimable again until 3 completions today.
FR-TODAY-7 — Completion → (optional photo) → submit for approval
Priority: P1 · Status: 🔨 partial — gate built; photo capture deferred (MVP-2) Acceptance
- Given an approval gate When I mark done Then status =
submittedand it enters the approver's queue. - Given no gate When I mark done Then tokens credit immediately via the single
ApprovalServiceearn path.
FR-TODAY-8 — Empty + welcome state
Priority: P2 · Status: ✅ built (#198) — celebratory empty state, never a blank screen.
FR-TODAY-9 — Overdue rollover behavior
Priority: P2 · Status: ❓ open decision — consistent handling (roll-forward / highlight / archive).
FR-TODAY-10 — List sort / priority order
Priority: P2 · Status: ❓ open decision — deterministic order (due time / routine order / manual).
Architecture considerations
- One data path —
TodayChoresBloc → Repository → client_sdkfacade; no directdrift/supabasein presentation. - Offline-first (P1) — Today must read and accept completions fully offline:
reads from the Drift write-through cache; completions queue and sync later
(Offline sync).
chore_completedmust be durable across an offline→online transition (no double-count on sync). - Assignment + eligibility resolved in the SDK —
assignedMemberIdsUnion(direct + per-room) andassignableMembers()(watch-only excluded) are service responsibilities, not bloc logic. effectiveTokens(now)computed at render; the daily temp-bonus sweep is wired via the T8 rollover caller.- Household-scoped RLS — Today never reads another household's chores; the cloud adapter relies on the household-scoped policies (SP3).
- Live updates — a
watch*stream keeps Today current as approvals land (also drives the Dashboard glance).
Design work (ahead of build)
Mostly already designed + built in the P1/P2 pass. Remaining design:
- Overdue treatment (FR-TODAY-9) — needs a visual decision before build.
- Optional inline "distance to goal" / balance indicator — design if adopted.
- By-kind ↔ by-room toggle and the empty/welcome state are designed; no new work.
Decisions (resolved for MVP-1)
Resolved — see the MVP-1 decisions log for the canonical record, rationale, and status legend (✅ decided · ⚖️ counsel confirms · 🔜 MVP-1.x).
- D-TODAY-1 — Overdue policy (FR-TODAY-9). ✅ Incomplete items roll forward as "overdue today" (carried with an overdue badge), not silently reset. Shared with D-ROUTINE-2.
- D-TODAY-2 — Sort order (FR-TODAY-10). ✅ Sort by overdue first → scheduled time → estimate ascending, within the By-kid / By-room grouping.
- D-TODAY-3 — Inline balance + goal-distance. ✅ Yes — a compact "balance · X to goal" line per member in the Today context (motivational, low cost), reduced on the child's own view.
Out of scope (MVP-1)
- Chore photo submissions + moderation → MVP-2.
- AI recommend suggestions on Today → recommender sub-project (stub only).
- TV / lean-back rendering of Today → deferred; note the supervised child-bounty exception on the TV dashboard (COPPA).