Repository navigation
S2 Backlog
Deliver, in both the Kotlin and the Flutter app, a signed-in user with a working core loop:
- BreakLoop measures their screen time and phone pickups (using the accelerometer).
- It sets a personalized goal that adapts to their behavior.
- It shows how much their screen time has dropped versus their baseline.
- It suggests offline activities that fit their current context.
- It keeps their progress synced to the cloud.
Behind both apps, a shared backend and analytics pipeline answers six business questions, one per member.
Each platform has three roles. The same role on both platforms builds the same functionalities, so the two apps stay coherent and the matching members can pair on shared work.
| Role | Kotlin member | Flutter member | Owns (per app) | Shared work (with the other platform's same role) |
|---|---|---|---|---|
| 1 · Auth, Goals & Sync | K1: [Name] | F1: [Name] | e. Authentication · d. Smart goals · f. Cloud sync | Backend (§4.1) |
| 2 · Tracking & Stats | K2: [Name] | F2: [Name] | a. Sensor · b. Type 2 BQ | Architecture docs (§4.3) |
| 3 · Recommendations & Analytics | K3: [Name] | F3: [Name] | c. Context-aware · design system · app instrumentation | Analytics pipeline (§4.2) |
This matrix makes sure every member covers each individually graded requirement. The patterns and BQs are suggestions: change them if the team prefers, then update the Sprint 2 report (§1.3).
| Member | BQ (§4.4) | Architectural pattern (contributes to) | Design pattern (owns) | Views (owns) | Functionalities |
|---|---|---|---|---|---|
| K1 | BQ-13 · Type * | Backend: BaaS / serverless with offline-first sync | Repository (offline-first data access) | Login, Sign-up, Home | e, d, f |
| K2 | BQ-03 · Type 2 | Kotlin frontend: MVVM | Observer (StateFlow from sensor and usage data to the UI) | Progress & Statistics (V7), Detailed Statistics (V8) | a, b |
| K3 | BQ-11 · Type 4 | Analytics: batch pipes-and-filters | Strategy (interchangeable recommendation scoring rules) | Offline Activities (V9), Activity Detail (V10) | c |
| F1 | BQ-06 · Type 2 | Backend: BaaS / serverless with offline-first sync | Factory (auth providers: email / Google) | Login, Sign-up, Home | e, d, f |
| F2 | BQ-01 · Type 1 | Flutter frontend: [MVVM / BLoC] | Adapter (platform channel wrapping native usage and sensor APIs) | Progress & Statistics (V7), Detailed Statistics (V8) | a, b |
| F3 | BQ-10 · Type 3 | Analytics: batch pipes-and-filters |
Facade (ContextProvider over clock, weather, location, interests) |
Offline Activities (V9), Activity Detail (V10) | c |
The six BQs together cover every type (1, 2, 3, 4, *), and each one depends only on data produced in this sprint.
Both apps implement the same functionalities, so the requirement mapping is identical for each platform.
| Req. | Functionality | Screens | Owner (Kotlin / Flutter) | Spec |
|---|---|---|---|---|
| a Sensor | Phone-Checking Detection | V8 Detailed Statistics | K2 / F2 | §5.a |
| b Type 2 BQ | Screen-Time Reduction Progress (answers BQ3) | V7 Progress & Statistics | K2 / F2 | §5.b |
| c Context-aware | Context-Aware Offline Activity Recommendations | V9 Offline, V10 Activity Detail | K3 / F3 | §5.c |
| d Smart feature | Personalized Adaptive Screen-Time Goals | Onboarding goal step, V1 Home | K1 / F1 | §5.d |
| e Authentication | Account Authentication (Firebase Auth) | Login, Sign-up, Password reset | K1 / F1 | §5.e |
| f External service / backend | Progress Cloud Sync (Firestore) | V1, V7 (data restored after login) | K1 / F1 | §5.f |
Requirement f asks that at least one functionality other than authentication be connected to the backend. Three functionalities meet it:
- f stores daily stats, goals, and streaks in Cloud Firestore.
- c reads the activity catalog from Firestore, syncs activity logs, and calls the external Open-Meteo weather API.
- d stores weekly goals in Firestore.
flowchart LR
subgraph Apps["Kotlin app / Flutter app"]
ACC[Accelerometer + screen events] --> PK[Pickup detection · a]
USG[Android usage events] --> TRK[Usage tracking · b]
PK --> DB[(Local database)]
TRK --> DB
DB --> GOAL[Adaptive goals · d]
GOAL --> DB
DB --> STATS[Stats & reduction · b]
CTX[Context: time, available time,<br/>interests, weather] --> REC[Recommender · c]
DB --> REC
EVT[Analytics events]
end
subgraph Firebase
AUTH[Auth · e]
FS[(Firestore)]
FA[Firebase Analytics]
end
subgraph Analytics["Analytics repository"]
ST[(Analytics store)] --> PROC[Processing jobs] --> DASH[BQ dashboards]
end
WX[Open-Meteo API] --> CTX
AUTH --> FS
DB <-->|sync · f| FS
FS -->|activity catalog| REC
EVT --> FA
FA --> ST
FS --> ST
On each device, the local database is the single source of truth, so both apps work offline (Q2, Q4). Firestore is the shared cloud copy, and both apps write the same schema (FND-08). The analytics pipeline combines events from both apps, identified by a platform field.
Owners: K1 + F1
| ID | Task | Pts | Owner |
|---|---|---|---|
| FND-08 | Shared domain model and data dictionary (schema both apps must follow) | 3 | K1 + F1 |
| BE-01 | Firebase projects (dev / prod); register both apps, including SHA-1 for Google Sign-In | 2 | K1 |
| BE-02 | Firestore data model and indexes | 3 | F1 |
| BE-03 | Security rules with emulator tests | 3 | K1 |
| BE-04 | Firebase Emulator Suite (stretch) | 2 | F1 |
| BE-05 | User provisioning on sign-up (users/{uid} and default settings) |
2 | F1 |
| BE-08 | Activity catalog in Firestore and seeding script | 3 | K1 |
| BE-21 | Backend repository as code: rules, indexes, seed scripts, Firebase CLI deploy | 2 | F1 |
| Subtotal | 20 |
Acceptance criteria
- Both apps sign in against the same Firebase project and read and write the same documents.
- Security-rule tests prove a user cannot read or write another user's data.
- The activity catalog can be re-seeded from the backend repository with one command.
Owners: K3 + F3
| ID | Task | Pts | Owner |
|---|---|---|---|
| DAT-01 | Event taxonomy shared by both apps (names, parameters, platform, appVersion) |
3 | K3 + F3 |
| DAT-05 | Pipeline design diagram with rationale (generation → collection → processing → storage → analysis) | 2 | K3 |
| DAT-06 | Ingestion and storage: Firebase Analytics events and Firestore aggregates exported to the analytics store | 5 | F3 |
| DAT-07 | Processing jobs in the analytics repository: cleaning, aggregation per user / day / device, privacy filters | 5 | K3 |
| DAT-08 | Dashboards answering the six implemented BQs | 3 | F3 |
| Subtotal | 18 |
Proposed design (pipes-and-filters, batch).
- Both apps emit Firebase Analytics events and write aggregates to Firestore (
dailyStats,activityLogs,devices). - A scheduled export moves this data into the analytics store.
- Processing scripts clean and aggregate it.
- Dashboards read the processed tables.
Each stage can be replaced or tested on its own. Check the export limits of your Firebase plan before choosing the store (see the General Backlog risks).
Acceptance criteria
- Every event carries
platformandappVersion, and both apps use identical event names. - No raw per-app usage for non-flagged apps and no personal identifiers reach the dashboards (Q9).
- Each of the six BQs has a dashboard or visualization fed by the pipeline.
Owners: K2 + F2 (diagrams). Every member contributes their own pattern write-ups.
| ID | Task | Pts | Owner |
|---|---|---|---|
| ARC-01 | Architecture overview, component diagrams (Kotlin, Flutter, backend/analytics), deployment diagram, each with rationale | 3 | K2 + F2 |
| ARC-02 | Sequence diagrams: sign-in and restore; usage tracking to analytics | 2 | K2 + F2 |
| ARC-03 | Architectural patterns implemented and documented (see §1.1) | 5 | All |
| ARC-04 | Design patterns: one per member, with code snippet and rationale (see §1.1) | 5 | All |
| ARC-05 | Architectural tactics mapped to quality scenarios, with owners | 3 | K2 + F2 |
| Subtotal | 18 |
Acceptance criteria
- Every diagram in the Sprint 2 report has a rationale and a responsible member.
- Each design pattern is visible in merged code, linked from its write-up.
Each member implements one BQ end to end (data → processing → visualization) and documents it in the Sprint 2 report (§4.5.1).
| ID | BQ | Type | Data used | Pts | Owner |
|---|---|---|---|---|---|
| BQ-01 | Devices without an accelerometer, by model and OS | 1 |
devices (DAT-03, TRK-06) |
3 | F2 |
| BQ-03 | Weekly screen-time decrease after interventions | 2 |
dailyStats, goals (shown in-app by STA-07) |
3 | K2 |
| BQ-06 | Screen time avoided after accepting an offline activity | 2 |
activityLogs, dailyStats
|
3 | F1 |
| BQ-10 | Offline recommendations and flagged-app time | 3 |
activityLogs, dailyStats.flaggedAppMin
|
3 | F3 |
| BQ-11 | Activity categories with the highest acceptance | 4 |
activityLogs (OFF-09) |
3 | K3 |
| BQ-13 | Activity acceptance vs. goal-streak length | * |
activityLogs, progress
|
3 | K1 |
| Subtotal | 18 |
Acceptance criteria (each BQ)
- The query or processing step is committed in the analytics repository.
- The result is shown in a dashboard or chart, reproducible from the stored data.
- The report entry states data used, analysis, result, and the responsible member.
Each functionality is specified once and implemented in both apps. The task tables list the points per platform and the owner in each app.
These are prerequisites for all functionalities, done once in each app.
| ID | Task | Pts | Kotlin | Flutter |
|---|---|---|---|---|
| FND-01 | Repository, branching, PR template, board | 1 | K1 | F1 |
| FND-02 | Project setup | 2 | K2 | F2 |
| FND-03 | Architecture skeleton (layers, DI, reactive state) | 3 | K1 | F1 |
| FND-04 | Navigation: auth → onboarding → main (5 tabs) | 3 | K1 | F1 |
| FND-05 | Local database and preferences | 5 | K1 | F1 |
| FND-06 | dev / prod variants and secrets | 2 | K1 | F1 |
| FND-07 | CI (stretch) | 3 | K3 | F3 |
| FND-09 | Background work, foreground-service base, restart after reboot | 3 | K2 | F2 |
| DS-01 | Theme | 3 | K3 | F3 |
| DS-02 | Reusable components | 5 | K3 | F3 |
| DS-03 | App header | 2 | K3 | F3 |
| DS-04 | Bottom navigation | 2 | K3 | F3 |
| DS-05 | Pixel-art assets for sprint screens | 5 | K3 | F3 |
| DS-07 | UI state pattern (loading / empty / error / content) | 2 | K3 | F3 |
| ONB-02 | Core permission flow: usage access, notifications, coarse location | 5 | K2 | F2 |
| ONB-09 | Privacy consent and analytics opt-in | 2 | K1 | F1 |
| SET-04 | Notification channels | 1 | K2 | F2 |
| DAT-02 | Instrument analytics events (per DAT-01) | 5 | K3 | F3 |
| DAT-03 | Device telemetry (model, OS, accelerometer, battery) | 3 | K3 | F3 |
| DAT-04 | Crashlytics | 1 | K2 | F2 |
| QA-01 | Unit tests for own domain logic | 5 | All | All |
| QA-02 | Database and sync tests | 3 | K1 | F1 |
| QA-06 | Analytics validation (events arrive, values match the app) | 3 | K3 | F3 |
| Subtotal per app | 69 |
Description. BreakLoop counts how many times a day the user picks up their phone and shows the result on Detailed Statistics (V8): today's pickups, the difference against their baseline, and the average interval between checks.
A screen that turns on is not always a pickup; a notification can wake the screen while the phone lies on a desk. To tell these apart, each screen-on event is classified with a short accelerometer reading:
- A phone that is tilted or moving counts as a pickup.
- A phone that stays flat and still counts as a wake-on-table.
Justification.
- The personas and empathy maps show that habitual checking (every 8–10 minutes in class) is invisible in total screen-time numbers (SF2, PAS3, PAS12).
- Counting pickups makes that automatic behavior visible, which is the first step toward changing it.
- It provides the data for BQ1, BQ7, and BQ14.
Implementation notes
| Kotlin | Flutter | |
|---|---|---|
| Screen-on / unlock | Dynamic BroadcastReceiver (ACTION_SCREEN_ON, ACTION_USER_PRESENT) in a specialUse foreground service |
Platform channel to a native receiver, running in a foreground-service plugin |
| Accelerometer |
SensorManager, registered for about 1.5 s per screen-on |
sensors_plus stream, subscribed for about 1.5 s per screen-on |
| Baseline | Unlock events from the previous 7 days of Android usage history (API 28+) | Same, through the platform channel |
| ID | Task | Pts | Kotlin | Flutter |
|---|---|---|---|---|
| TRK-04 | Pickup detection: screen events, accelerometer classification window, persistence | 8 | K2 | F2 |
| TRK-05 | Pickup metrics: daily count, vs. baseline, average interval | 2 | K2 | F2 |
| TRK-06 | Sensor capability check; unlock-only fallback; capability saved to devices
|
2 | K2 | F2 |
| TRK-08 | Battery budget: sensor only active during windows; profile a full day | 3 | K2 | F2 |
| STA-05 | Deep Stats pickup card (V8) | 2 | K2 | F2 |
| Subtotal per app | 17 |
Acceptance criteria
- Tracking keeps running after the app is closed and restarts after a reboot, with a low-priority persistent notification.
- Waking the screen with the phone flat on a table is not counted; lifting and turning on the screen is counted.
- Deep Stats shows today's pickups, the difference vs. baseline, and the average interval, updating within 1 minute.
- Without an accelerometer, the app counts unlocks instead, shows a short note, and records the capability (BQ1).
- The accelerometer is only active during classification windows. Battery impact is under 2 % per day on the test device.
- The intentionality gauge on V8 is hidden until SHD-09 (Sprint 3).
Demo: notification with the phone on a table (count unchanged) → pick up and unlock (count +1) → open Deep Stats.
Business question answered: BQ3. How much does users' weekly screen time decrease after using the app's interventions?
Description. Progress & Statistics (V7) answers BQ3 directly for each user. It shows:
- today's screen time;
- a weekly chart against the goal line;
- the weekly average compared with the baseline week, as a percentage change and as progress toward the −20 % project target;
- "Tamed distraction loops": the time saved on each flagged app compared with that app's baseline.
Justification.
- This is a Type 2 question because the answer goes to the user to improve their own experience.
- It measures the app's primary objective (the −20 % target in Sprint 1 §1.1).
- Existing screen-time reports only show the problem in hindsight (empathy maps 1 and 3). Framing the data as progress against the user's own baseline turns it into feedback and motivation.
Implementation notes
| Kotlin | Flutter | |
|---|---|---|
| Usage data |
UsageStatsManager.queryEvents (resumed / paused pairs) |
Usage-stats plugin or platform channel to the same API |
| Periodic aggregation | WorkManager (15 min) | workmanager plugin (15 min) |
| Chart | Compose Canvas | fl_chart |
| ID | Task | Pts | Kotlin | Flutter |
|---|---|---|---|---|
| ONB-04 | Flag distracting apps and set per-app limits | 5 | K2 | F2 |
| TRK-01 | Per-app foreground time from usage events | 8 | K2 | F2 |
| TRK-02 | Aggregation job; midnight rollover; time-zone changes | 5 | K2 | F2 |
| TRK-03 | Flagged-app usage vs. limit; cushion left | 3 | K2 | F2 |
| STA-02 | Stats overview metric cards | 3 | K2 | F2 |
| STA-03 | Weekly screen-rhythm chart with goal line, average, breaches | 5 | K2 | F2 |
| STA-04 | Tamed distraction loops (time saved per flagged app) | 3 | K2 | F2 |
| STA-07 | Reduction-vs-baseline insight and progress toward −20 % | 3 | K2 | F2 |
| Subtotal per app | 35 |
Acceptance criteria
- Daily screen time matches Android's Digital Wellbeing to within ±5 % on the test devices.
- The weekly chart shows Monday–Sunday with a goal line. The weekly average and breach count are correct.
- The reduction card shows "Your weekly average is X % lower / higher than your baseline" and progress toward −20 %.
- "Time saved" is defined as that app's baseline daily average minus today's usage, never shown as negative, and documented in the data dictionary.
- Days with partial data (for example, the install day) are excluded from averages.
- Without usage access, the screen shows an empty state with a button to grant it.
Demo: open Stats after a few days of use → compare with Digital Wellbeing → read the reduction vs. baseline.
Description. At the top of the Offline screen (V9), a "Suggested for right now" card recommends the best activity for the user's current context. It includes a short reason, such as "Sunny and you have 15 min: take a walk." The user chooses how much time they have (5 / 15 / 30 min). Tapping the card opens Activity Detail (V10), where "Start & Log" records the activity.
The recommendation uses four kinds of context:
| Context | Source |
|---|---|
| Time of day and day type | Device clock |
| Available time | User selection |
| Weather | Open-Meteo API using coarse location |
| Interests and history | Onboarding interests and recent activity logs |
Justification.
- Interviews identified boredom and unstructured time as key triggers (PAS2, PAS8).
- A suggestion that fits the moment is more likely to be accepted than a generic list, for example no outdoor walk when it's raining or at night, and nothing longer than the time available.
- It implements CAS1 and the quality scenarios Q1, Q2, and Q8.
- Acceptance logs feed BQ6, BQ10, BQ11, and BQ13.
Recommender.
score = interestMatch·w1 + weatherFit·w2 + timeOfDayFit·w3 + durationFit·w4 − recentRepeatPenalty
Activities longer than the available time are excluded. Both apps use the same rules and weights so their results match.
Implementation notes
| Kotlin | Flutter | |
|---|---|---|
| Weather client | Retrofit | dio or http |
| Location | Fused Location Provider (coarse) | geolocator (low accuracy) |
| Catalog cache | Room | drift / sqflite |
| ID | Task | Pts | Kotlin | Flutter |
|---|---|---|---|---|
| ONB-05 | Interest profile in onboarding | 3 | K3 | F3 |
| OFF-01 | Local activity catalog cache (from BE-08) with bundled JSON fallback | 3 | K3 | F3 |
| OFF-02 | Offline list with category filter chips (V9) | 3 | K3 | F3 |
| OFF-03 | Activity Detail with Start & Log, timer, XP recorded (V10) | 3 | K3 | F3 |
| OFF-04 |
ContextProvider (time of day, day type, available time, weather, interests, history) |
5 | K3 | F3 |
| OFF-05 | Recommender scoring and cold-start fallback | 5 | K3 | F3 |
| OFF-06 | "Suggested for right now" card with time selector and reason label | 2 | K3 | F3 |
| OFF-07 | Weather context with coarse location and offline label | 3 | K3 | F3 |
| OFF-09 | Acceptance tracking (suggested / accepted / completed) | 2 | K3 | F3 |
| BE-09 | Weather service client: 30-minute cache, timeout, offline handling | 3 | K3 | F3 |
| BE-10 | Activity log sync to activityLogs, including the context snapshot |
2 | K3 | F3 |
| Subtotal per app | 34 |
Acceptance criteria
- A suggestion appears within 3 seconds and can be started in at most 3 taps (Q1).
- In airplane mode, a suggestion still appears from the local catalog with an "offline-based" label and no error (Q2).
- A brand-new user with only interests selected receives suggestions (Q8).
- No outdoor activities when it is raining or at night. Nothing longer than the selected available time.
- Each suggestion shows the reason it was chosen.
- Completed and accepted activities are saved locally and synced to
activityLogswith their context.
Demo: show a suggestion at the current time → change available time from 30 to 5 minutes (suggestion changes) → airplane mode (offline label).
Description. Instead of a fixed generic limit, BreakLoop learns each user's baseline from their own usage history. It then sets a gradual daily goal toward a 20 % reduction.
Every week the goal adapts to how the user actually performed. It gets stricter when they succeed and eases off when they struggle. The user can accept or override each suggestion. The Home card (V1) and the streak use this goal.
Justification.
- The feature is "smart" because it uses the user's own historical data to make a personalized decision and keeps re-evaluating that decision (SF6, PAS7).
- Users abandon generic limits they can't meet (empathy maps). A gradual, adaptive goal addresses the "difficulty maintaining change over time" problem.
- It also produces the baseline that functionality b reports against.
Algorithm. Let B be the baseline (median daily screen time over the previous 7 days) and T = 0.8 × B the target.
- Initial goal: G₀ = 0.95 × B.
- Each Monday, count the days the goal was met last week, then:
| Days goal met | New goal |
|---|---|
| 5 or more | G = max(T, G − 0.05 × B) (tighten) |
| 3 or 4 | G stays the same |
| 2 or fewer | G = min(B, G + 0.025 × B) (ease off) |
- If the user overrides the goal, the algorithm continues from their value.
- If less than 7 days of history exist, B uses the available days. If there are fewer than 3, the goal is re-evaluated after the first week of tracking.
| ID | Task | Pts | Kotlin | Flutter |
|---|---|---|---|---|
| GOAL-01 | Baseline computation (median of last 7 days, fallback rules) | 3 | K1 | F1 |
| GOAL-02 | Initial goal suggestion toward −20 % | 3 | K1 | F1 |
| GOAL-03 | Weekly adaptive adjustment (periodic job, Monday) | 5 | K1 | F1 |
| GOAL-04 | Goal review UI: accept / override, "why this goal" | 2 | K1 | F1 |
| GOAL-05 | Streak engine: consecutive days under goal, best streak | 3 | K1 | F1 |
| ONB-06 | Onboarding baseline and first-goal step | 3 | K1 | F1 |
| STA-01 | Home screen-time card: today vs. goal, cushion left | 3 | K1 | F1 |
| Subtotal per app | 22 |
Acceptance criteria
- After granting usage access, the user sees their baseline and a suggested goal with an explanation within 5 seconds.
- The goal is saved locally and in
goals/{weekStart}withsource= suggested or user. - Unit tests cover every adjustment branch (tighten / keep / ease off), the target floor, and the baseline ceiling. Both apps pass the same test cases.
- The Home card shows today's screen time, % vs. goal, and cushion left.
- The streak increases only for closed days under goal and never breaks because of a missing sync.
Demo: run onboarding on a device with history → inject a test week with the goal met 5 times and show the tightened goal → override it.
Description. Users create an account and sign in with email and password or Google. The session persists between launches. Password reset is available by email. Logging out clears the user's local data from the device. On sign-up, the user's profile document is created in Firestore (BE-05).
Justification.
- Accounts are required to back up and restore progress (f, Q4).
- They are required for future social features (V11, V12).
- They keep each user's data isolated (Q9).
- Google sign-in reduces onboarding friction for students.
| Kotlin | Flutter | |
|---|---|---|
| SDK | Firebase Auth Android SDK | firebase_auth |
| Google Sign-In | Credential Manager | google_sign_in |
| ID | Task | Pts | Kotlin | Flutter |
|---|---|---|---|---|
| AUTH-01 | Login and sign-up screens with validation | 3 | K1 | F1 |
| AUTH-02 | Firebase Auth email / password; error mapping | 3 | K1 | F1 |
| AUTH-03 | Google Sign-In (stretch) | 3 | K1 | F1 |
| AUTH-04 | Session persistence, splash routing, logout clearing local data | 2 | K1 | F1 |
| AUTH-05 | Password reset (stretch) | 1 | K1 | F1 |
| Subtotal per app | 12 |
Acceptance criteria
- Invalid email or a password under 8 characters shows inline errors before any request is sent.
- "Email already in use", "wrong password", and "no connection" each show a clear message, never a raw exception.
- A signed-in user reopening the app goes straight to Home; a signed-out user goes to Login.
- After logout, a different user signing in on the same device sees none of the previous user's data.
- An account created in one app can sign in to the other.
Description. The user's daily stats, goals, and streak progress are stored in Cloud Firestore. Sync is offline-first:
- Everything is written locally first and appears immediately.
- A background job uploads changes whenever a network is available.
- A daily close job finalizes each day and updates the streak.
After signing in on a new or reinstalled device, the user's history, goal, and streak are restored.
Justification.
- Losing a streak or weeks of progress would break the motivation loop the product relies on (Q4, Q11).
- Cloud storage is the prerequisite for social features and for the analytics pipeline that answers the BQs.
- It implements Q4 (sync without loss), Q11 (recovery), Q12 (idempotent writes), and Q9 (only flagged-app times leave the device).
| Kotlin | Flutter | |
|---|---|---|
| SDK | Firebase Firestore Android SDK | cloud_firestore |
| Background upload | WorkManager | workmanager plugin |
| ID | Task | Pts | Kotlin | Flutter |
|---|---|---|---|---|
| BE-06 | Daily stats sync (dailyStats/{date}), idempotent, backoff retries |
5 | K1 | F1 |
| BE-07 | Daily close job: finalize day, evaluate goal, update progress/current in a transaction |
5 | K1 | F1 |
| BE-12 | Restore on login: goals, last 30 days of stats, progress, activity logs | 3 | K1 | F1 |
| Subtotal per app | 13 |
Acceptance criteria
- A change to today's stats reaches Firestore within 15 minutes when online.
- Going offline right after meeting the goal still shows the updated streak immediately. It syncs on reconnect without duplicates or a broken streak (Q4).
- Syncing the same day twice leaves exactly one
dailyStats/{date}document. - If the phone was off at midnight, the daily close runs on the next app open and closes each missed day exactly once.
- Reinstalling and signing in restores the goal, streak, and last 30 days of stats.
- Firestore contains per-app minutes only for flagged apps.
Demo: meet the goal in airplane mode (streak updates) → reconnect and show the Firestore console → reinstall and sign in (data restored).
| Block | Kotlin | Flutter | Shared |
|---|---|---|---|
| Per-app enablers | 69 | 69 | — |
| a. Phone-Checking Detection | 17 | 17 | — |
| b. Screen-Time Reduction Progress | 35 | 35 | — |
| c. Context-Aware Recommendations | 34 | 34 | — |
| d. Adaptive Goals | 22 | 22 | — |
| e. Authentication | 12 | 12 | — |
| f. Progress Cloud Sync | 13 | 13 | — |
| Backend | — | — | 20 |
| Analytics pipeline | — | — | 18 |
| Architecture and design | — | — | 18 |
| Business questions | — | — | 18 |
| Total | 202 | 202 | 74 |
| of which stretch | 7 (FND-07, AUTH-03, AUTH-05) | 7 | 2 (BE-04) |
Shared points are included where the member owns or co-owns the item. Co-owned items are split equally.
| Member | App work | Shared work | Total |
|---|---|---|---|
| K1 / F1 | ~69 (e, d, f, foundation, sync tests) | ~16 (backend, own BQ, own patterns) | ~85 |
| K2 / F2 | ~64 (a, b, tracking enablers) | ~12 (architecture docs, own BQ, own patterns) | ~76 |
| K3 / F3 | ~69 (c, design system, instrumentation, CI) | ~15 (analytics pipeline, own BQ, own patterns) | ~84 |
This is a heavy sprint. Re-point during planning. If the Compose and Flutter prototypes already exist as code, the DS items become mostly refactoring. If time runs short, drop the stretch items first, then STA-04.
- Week 1, day 1–2: agree on FND-08 (schema), DAT-01 (event taxonomy), and the patterns in §1.1, since both apps depend on them. Set up BE-01 – BE-03.
- Foundation and design system in both apps (per-app enablers).
- Authentication (e), which unblocks every backend-connected item.
- Usage tracking and pickup detection (a, b) in parallel with recommendations (c).
- Adaptive goals (d), then the Stats screens (b), since they depend on tracking and the baseline.
- Cloud sync (f) and app instrumentation, then the analytics pipeline and the six BQs.
- Final days: diagrams, pattern write-ups, analytics validation, and the Sprint 2 report.
- Focus sessions, App Shield, gamification (pet, badges, XP applied to levels), Wind-Down, settings, and social features. These are planned for S3 and Later in the General Backlog.
- Screens V2–V6, V11, and V12 can remain as static prototype UI.
As defined in the General Backlog. In addition, each functionality must be demonstrated on a physical device in both apps, using its demo script.