v4.1 — Engagement & Retention
Four small, independent reasons to come back tomorrow — a private journal note, real privacy controls, an honest pledge at signup, and a home-screen glance that never asks you to open the app.
Summary
Objectuve's Phase 4 roadmap item ("Engagement & Retention") had been open since the original PRD in April 2026, with most of its original five features shipped or superseded over time. Four gaps remained: users had no lightweight way to reflect on a check-in, no way to opt out of social features or hide from discovery, no upfront statement of the product's anti-addictive philosophy, and no way to check progress without opening the app at all.
v4.1 closed all four gaps as one milestone. Each is a small, single-user-facing surface shipped behind its own kill-switch flag, deliberately built with no shared schema and no ordering dependency between them — this let all four ship independently, in risk order (lightest first, native widgets last), and be rolled back individually if needed. The Daily Micro-Journal adds an optional one-sentence note to any habit check-in, feeding the Coach's pattern reflection without adding a required step. Privacy Controls give users two account-level toggles — go solo (hide community UI) and go private (drop out of search/discovery) — with server-side fail-closed enforcement on every surface, not just the UI. The Onboarding Philosophy Pledge is a skippable slide, early in signup, that states the anti-social-app stance in the user's own words before they've committed to anything. Home Screen Widgets are the biggest lift of the four: a native iOS WidgetKit and Android App Widget, fed by a custom Capacitor bridge, that show today's habits and current streak on the home screen — read-only, tap-to-open, the literal embodiment of "check progress without entering the app."
All four phases merged to the milestone integration branch gsd/v4.1-engagement-retention, then reached staging and production users via the master-flip PR on 2026-07-12 (tag v4.0.0), which promoted all four flags together per the delivery-isolation policy locked at milestone open.
Goal
Deepen the daily loop and give users reasons to come back — human- and coach-driven — while staying true to the anti-social-app philosophy (check progress without being pulled into the app). Four independent, single-user–facing features, each shippable on its own behind a per-feature flag.
Scope — What Shipped
habit_completions.note(nullable, ≤280 chars) +GoalTracking::CheckInHabit(note:)+HabitCompletionType#note, owner-scoped so a note never leaks via public/community/ally goal readsHabitCard.vueopt-in note capture on check-in; Coach context (Ai::BuildCoachContext) folds recent notes into its existing reflections signal — no new AI read pathusers.go_it_alone/users.private_modecolumns +UpdatePrivacySettingsinteraction/mutation (self-only, fails closed)search_usersresolver excludesprivate_modecandidates;go_it_alonesuppresses ally/community suggestion surfaces; both gated on the target user's own flag statePrivacyControlsCard.vuein Settings → Privacy — "Go solo" and "Private profile" toggles- Shared onboarding values module
ourStoryValues.ts; new skippablePhilosophySlide.vueat onboarding index 1, drawing from the same content as the public/our-storypage — no copy drift - Custom Capacitor plugin
WidgetBridge(Swift + Java) writing a habits+streak snapshot to iOS App Group / Android SharedPreferences, with an immediate widget-reload trigger - Native iOS WidgetKit (
SmallWidgetView/MediumWidgetView) + Android App Widget rendering all 5 states (default, all-done, empty, stale, first-run) in both themes; whole-widget tap deep-links to the dashboard - In-app
WidgetSettingsRow.vue+WidgetSetupSheet.vue— discoverable, fail-closed widget setup affordance in Settings - Four independent kill-switch flags:
micro_journal_enabled,privacy_controls_v1,onboarding_pledge_enabled,home_widgets_enabled— each registered infeatureFlags.tsand PostHog, fail-closed - New feature doc
docs/features/home-widgets.md; updates todocs/architecture/data-models.md, GraphQL mutation docs,docs/product/onboarding-flow.md,docs/operations/mobile-builds.md, anddocs/product/roadmap.mditems 24/25/26/29
Phases
| Phase | Name | Status | Plans | Highlights |
|---|---|---|---|---|
| 1 | Daily Micro-Journal | Shipped | 1 | Optional note on check-in, Coach pattern reflection, owner-scoped privacy |
| 2 | Privacy Controls — Go It Alone & Private Mode | Shipped | 1 | Two self-only account toggles, fail-closed search/suggestion filtering |
| 3 | Onboarding Philosophy Pledge | Shipped | 1 | Skippable pledge slide sourced from existing /our-story copy |
| 4 | Home Screen Widgets (iOS/Android) | Shipped | 1 | Native WidgetKit + App Widget, custom shared-storage bridge, in-app setup |
Key Decisions
- Per-feature flags, not one umbrella flag — each of the four surfaces is a small, single-user blast radius with no shared schema, so each got its own kill switch (
micro_journal_enabled,privacy_controls_v1,onboarding_pledge_enabled,home_widgets_enabled) instead of v4.0 Teams' singleteams_enabledtrunk-flag model. - Milestone integration branch, not flags-on-master — every phase PR merges to
gsd/v4.1-engagement-retention, not master; a single master-flip PR at milestone close promotes all four flags to staging/production together. This is the house precedent from v1.10/v1.16/v2.x, chosen over v4.0's flags-on-master trunk model because "shipped" here means "merged to the integration branch, green, Vicki-closed" — staging/production exposure is deliberately deferred to one coordinated flip. - Journal privacy is enforced at the GraphQL type layer, independent of the Privacy Controls phase —
HabitCompletionType#noteis scoped to the completion's owner regardless of whether that user hasgo_it_alone/private_modeset. The two privacy guarantees don't depend on each other, by design. - Widgets are read-only in V1 — interactive check-in from the widget itself is an explicit, documented fast-follow, not shipped here. The widget's only interaction is "tap to open the app."
- Custom native bridge over
@capacitor/preferences— the widget-reload trigger needs a native call regardless, so a small custom Capacitor plugin (WidgetBridge) avoided a split-brain risk between a generic preferences plugin and the App Group/SharedPreferences the native widgets actually read from. - Android widget in Java, not Kotlin — avoided introducing a second native-Android build toolchain for one phase;
RemoteViews, not Glance, for the same reason.
Requirements Coverage
23 / 23 requirements satisfied — JOURNAL 5/5, PRIVACY-J 1/1, PRIVACY 6/6, PLEDGE 5/5, WIDGET 6/6.
| Category | Count | Status |
|---|---|---|
| JOURNAL-* | 5 | All satisfied |
| PRIVACY-J | 1 | Satisfied |
| PRIVACY-* | 6 | All satisfied |
| PLEDGE-* | 5 | All satisfied |
| WIDGET-* | 6 | All satisfied (2 success criteria — real-device rendering — pending human verification; see Tech Debt) |
Full requirements list and per-phase detail: v4.1-engagement-retention-ROADMAP.md on GitHub. No separate REQUIREMENTS.md file exists for this milestone — requirements are defined inline per phase in the ROADMAP.
Outcomes
Users can now: attach a private note to any habit check-in and have their Coach reference the pattern over time; opt out of social features entirely or hide from search/discovery, enforced server-side rather than just hidden in the UI; see the product's anti-addictive stance stated plainly during onboarding, skippable if they'd rather get started; and glance at today's habits and current streak from their home screen without opening the app — the clearest embodiment yet of the "check without entering" philosophy. All four features shipped to real users 2026-07-12 via the master-flip on tag v4.0.0 — see ionic_frontend/CHANGELOG.md [4.0.0] - 2026-07-12.
Tech Debt
- (Phase 4) Real-device/simulator visual verification of both native widgets is still outstanding — no sandbox across the phase could render either widget end-to-end (a reproducible Android System UI ANR; broken iOS Simulator-toolchain layers). Every acceptance check came from source-level UI-SPEC tracing and Storybook capture of the in-app surfaces only. A human with Xcode/Android Studio + device access should confirm both widgets against Desi's 12 mockup PNGs before treating this as fully visually verified.
- (Phase 4) First-run widget glyph diverges by platform (iOS gradient vs. Android flat circle) — no native primary/primary-light color-token pair was defined in the UI-SPEC. Needs a design confirmation.
- (Phase 4) Android in-app setup step 2 copy ("Tap Widgets, then find Enkidu.") is an inferred variant, not verbatim spec text — needs sign-off.
(Milestone) The master-flip PR promoting all four flags to staging/production, and the resulting version tag, is deferred release work — not part of this docs close.Resolved 2026-07-12: master-flip landed on tagv4.0.0(seeionic_frontend/CHANGELOG.md[4.0.0] - 2026-07-12).
Related Artifacts
- Roadmap: v4.1-engagement-retention-ROADMAP.md
- Milestone Audit: v4.1-engagement-retention-MILESTONE-AUDIT.md
- PRD: Phase 4: Engagement & Retention PRD — note: the original PRD's five features predate this milestone's actual scope; see the PRD's own Implementation Status table for the full history of what shipped where
- Feature doc: docs/features/home-widgets.md
- Git tag:
v4.0.0(cut 2026-07-12, master-flip) - Merge PRs: #1271, #1281, #1300, #1306, #1321, #1325, #1331
Related Commits
6a65f830a— feat(journal): Phase 1 — daily micro-journal note on check-in (#1271)20a07e1fc— feat(privacy): Phase 2 — go-it-alone & private-mode controls (#1281)1c48f186c— docs(privacy): data-models, GraphQL reference, roadmap for privacy controls (OBJ-1146)c8f2645b3— feat(onboarding): Phase 3 — philosophy pledge slide (#1300)ec5af0e08— feat(widgets): WidgetBridge native bridge + iOS App Group + Android widget skeleton (#1306)8d5689850— feat(widgets): iOS WidgetKit + Android widget UI for all 5 states (#1321)e2d0ac44e— feat(widgets): in-app "Add widget" affordance (Stage 4) (#1325)d2e9bf3e4— docs(widgets): Stage 5 docs pass for v4.1 Phase 4 home-screen widgets (#1331)
Last updated: 2026-07-18 Version: v4.0.0 (master-flip landed 2026-07-12)