Skip to content

feat: post-celebration Astra review moment + Android release tsconfig fix (#382) - #398

Merged
thomasluizon merged 2 commits into
mainfrom
feature/382-review-moment
Jul 4, 2026
Merged

feat: post-celebration Astra review moment + Android release tsconfig fix (#382)#398
thomasluizon merged 2 commits into
mainfrom
feature/382-review-moment

Conversation

@thomasluizon

@thomasluizon thomasluizon commented Jul 4, 2026

Copy link
Copy Markdown
Owner

Closes #382

What

Three bundled changes:

1. Post-celebration Astra review moment (Android)

  • New top-priority 'review' kind in the shared engagement-prompt arbitration (review 3 > milestone-share 2 > referral 1) — reuses the single armed slot, once-per-key guard, and shared 14-day cooldown (markEngagementPrompted burns it when the sheet shows).
  • Triggers: streak milestones 7/14/30/100/365 (armed in use-habits onSuccess, after trackCompletion so completion fix recursive parent completion prompts #20 counts for the same moment) + any level-up (armed in _layout beside the referral arming). Eligibility floor (onboarding + 10 completions + 2 distinct active days + not accepted + snooze lapsed — lowered from the pre-existing 20/5 for launch-week review velocity, product decision on top of Review prompt upgrade — post-celebration Astra-branded review moment (Android) #382) checked at arm time AND display time via isReviewMomentEligible.
  • Surface: Astra-branded TrueSheet (ReviewMomentSheet) mirroring MilestoneSharePrompt — waits for celebrations to fully settle (+500ms), personalized copy referencing the actual streak/level, en + pt-BR.
  • Inline ReviewReminderCard deleted; reviewReminder removed from the shared engagement-slot rotation on both platforms.
  • Guideline compliance: the old sentiment pre-qualification copy ("Enjoying Orbit?") is deleted; no rate-gating anywhere; native review card untouched; every dismissal path (swipe, back, "Not now") = one code path = existing 120-day snooze; accept = never again. expo-store-review + Play URL fallback unchanged.

2. Android Release build fix (run 28720033241)

:app:createBundleReleaseJsAndAssets died with Invariant Violation: Failed to collapse — SDK 56 @expo/cli resolves the tsconfig extends chain through Metro's file map; in the isolated .release-mobile workspace the lookup of ../../tsconfig.base.json misses on Linux and the node_modules fallback (an upward-traversing specifier) crashes metro-file-map. The Sentry-upload failure was downstream fallout (no bundle/sourcemap existed).

Fix: prepare-release-workspace.js now copies tsconfig.base.json into the copied apps/mobile/ and rewrites extends to ./tsconfig.base.json, keeping resolution inside the Metro project root (the same lookup mechanism that finds tsconfig.json itself). Verified locally in a faithful isolated workspace: the exact CI command (expo export:embed --platform android --dev false) produces a complete 15MB Hermes bundle (6375 modules, all @/ + @orbit/shared aliases resolving). The pre-fix crash is Linux-specific and does not reproduce on Windows; final confirmation is the next manual Android Release dispatch after merge.

3. Level-up overlay: Continue button removed (both platforms)

The pill was redundant (tap-anywhere, 6s auto-dismiss, and back/escape all already dismiss) and miscentered. Removed on web + mobile; dismissal behavior covered by updated tests.

Platform parity

Validation

  • type-check: all 3 workspaces ✓
  • tests: shared 1384 ✓ · mobile 929 ✓ · web 2105 ✓ (new: 10-case sheet test, eligibility predicate tests, review arbiter tests, workspace-tsconfig test, overlay dismissal tests)
  • lint: 0 errors (also fixed a pre-existing unused-import warning in trial-banner.tsx)
  • parity-checker: PAIRED · i18n-syncer: en/pt-BR in sync

🤖 Generated with Claude Code

…se tsconfig fix (#382)

- new top-priority 'review' engagement-prompt kind; TrueSheet review moment
  post streak-milestone/level-up celebrations; inline ReviewReminderCard removed
- rate-gating copy deleted; dismiss=120d snooze, accept=one-shot; en+pt-BR
- prepare-release-workspace: keep tsconfig extends inside the project root
  (SDK 56 @expo/cli "Failed to collapse" crash in Android Release)
- level-up overlay: remove Continue button on both platforms

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@vercel

vercel Bot commented Jul 4, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
orbit-ui-mobile-web Ignored Ignored Jul 4, 2026 11:23pm

Request Review

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review: PR #398 — post-celebration Astra review moment + Android release tsconfig fix

Scope: PR #398 in thomasluizon/orbit-ui-mobile (frontend only — no orbit-api changes)
Recommendation: APPROVE

Summary

Three bundled, well-scoped changes: (1) a new mobile-only Astra-branded "review moment" sheet that reuses the existing shared engagement-prompt arbitration (adds a top-priority 'review' kind), replacing the old inline ReviewReminderCard; (2) a targeted fix to prepare-release-workspace.js keeping the tsconfig extends chain inside the isolated release workspace to unblock the Android release build; (3) removal of the redundant "Continue" button from the level-up overlay on both web and mobile. Traced the eligibility/arbitration logic (arm-time + display-time re-check, once-per-key guard, 120-day snooze, one-shot accept) end-to-end and it is internally consistent; no dead code, type-safety, or security issues found in the diff.

Findings

Critical

None.

High

None.

Medium

None.

Low / Info

  • Two new locale strings (reviewMoment.streakBody / levelBody in both en.json and pt-BR.json) use em dashes, which DESIGN.md:185 bans in user-facing copy. Not posting as a blocking finding per the signal gate — it's a pure style nit and the codebase already has many pre-existing em-dash instances elsewhere in the same locale files, so this isn't a regression specific to this PR's rigor.

Subagents

Agent Verdict
parity-checker PAIRED — level-up overlay button removal is symmetric on web+mobile; the review-moment surface is mobile-only by design (no web equivalent to a native app-store review flow), which is a legitimate platform-adapter exception per root CLAUDE.md, and web's engagement slot already always returned reviewReminder: false
i18n-syncer IN SYNC — all 7 reviewMoment.* keys present in both en.json/pt-BR.json with matching placeholders; no orphaned reviewPrompt.* callsites left after the key rename
contract-aligner N/A — no orbit-api changes and no packages/shared/src/types/*/endpoints.ts changes; the shared engagement-prompt store changes are client-only persisted state, not a network contract
security-reviewer N/A — no orbit-api code changed

Validation

Skipped per CI instructions — Build / Unit Tests / SonarCloud run as separate required checks on this PR.

Deferred — N/A dimensions & files not verdicted

  • Dimension 13 (Backend hard rules): N/A — no orbit-api files in this diff.
  • Dimension 14 (FEATURES.md parity): N/A — this is an internal engagement-mechanic swap (review reminder card → review moment sheet), not a new headline feature; consistent with the existing convention where the analogous referral-prompt and milestone-share-prompt mechanics also aren't tracked as their own FEATURES.md rows.
  • Contract-aligner / security-reviewer dimensions: gated off because the diff touches neither orbit-api nor the shared type/endpoint contract — not "unverifiable," genuinely out of scope for this diff.
  • Every other changed file (mobile stores/hooks/components, web overlay, shared engagement-prompt-store/i18n) received a verdict during the dimension walk.

What's good

  • Eligibility is checked twice by design (arm time in use-habits.ts/_layout.tsx, redisplay time in review-moment-sheet.tsx), and the "once-per-key" + snooze + one-shot-accept guards correctly self-heal (an armed-but-now-ineligible prompt gets cleared on next render) without any observed race.
  • The Android release fix carries a real WHY comment with an upstream URL, exactly per the comment policy, and ships with a dedicated regression test (prepare-release-workspace.test.ts) asserting the rewritten extends chain.
  • Thorough test coverage added for the new eligibility predicate, the arbiter priority ordering, and the sheet's visibility/dismissal paths.

Recommendation

Approve as-is. No action required before merge.

…days

Launch-week velocity: an engaged new user now qualifies at their day-2
level-up instead of day 5+. 2-day minimum keeps the one-shot-per-120-days
ask away from first contact.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@sonarqubecloud

sonarqubecloud Bot commented Jul 4, 2026

Copy link
Copy Markdown

@thomasluizon
thomasluizon merged commit 654ebac into main Jul 4, 2026
10 checks passed
@thomasluizon
thomasluizon deleted the feature/382-review-moment branch July 4, 2026 23:36

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review: PR #398 — feat: post-celebration Astra review moment + Android release tsconfig fix (#382)

Recommendation: REQUEST CHANGES

Summary

This PR bundles three changes: (1) a new mobile-only "Astra review moment" bottom sheet replacing the old inline ReviewReminderCard with a post-celebration Play Store review prompt (streak milestones 7/14/30/100/365 + any level-up, eligibility floor lowered to 10 completions / 2 active days), (2) removal of the redundant "Continue" button from the level-up overlay on both platforms, (3) an Android release-build tsconfig resolution fix. The engineering is solid — eligibility is checked consistently at arm time and display time through one shared pure function, arbitration priority is correct, tests are thorough, and the old mechanism's dead code is fully removed. Two issues surfaced below (both verified directly against the diff), one High and one Medium.

Findings

Critical: None

High

[HIGH] FEATURES.md not updated for the new review-moment feature

  • location: FEATURES.md (repo root)
  • issue: This PR introduces a materially new, named user-facing mechanism — a mobile-only Astra-branded review-moment sheet with its own eligibility rules and its own arbitration priority in the shared engagement-prompt store — fully replacing ReviewReminderCard. FEATURES.md documents comparable/adjacent mechanisms at the same granularity (Milestone sharing row 109, Celebration overlays row 184) but gets no new row for this one.
  • risk: Readers of FEATURES.md, and any downstream copy derived from it, have no way to discover Orbit now prompts for a Play Store review, or under what conditions/platform.
  • fix: Add a row (e.g. in "Social & Growth" or "Gamification & Rewards"): description, Gating = Free, Platform = Mobile-only, mirroring the Milestone sharing row shape.

Medium

[MEDIUM] Em dashes in shipped review-moment copy violate the DESIGN.md ban

  • location: packages/shared/src/i18n/en.json:247-248, packages/shared/src/i18n/pt-BR.json:247-248
  • issue: reviewMoment.streakBody and reviewMoment.levelBody contain a literal em dash in both locales — e.g. "You showed up {count} days in a row — that's real momentum..." and the pt-BR equivalent ("...seguidos — isso é ritmo de verdade...").
  • risk: DESIGN.md explicitly bans em dashes in user-facing copy (DESIGN.md:185: "No em dashes in copy. Use a comma, period, or hyphen."); this ships directly in production strings shown to users.
  • fix: Replace with a period or comma in both locales, e.g. "You showed up {count} days in a row. That's real momentum."

Low / Info: None (nothing else met the signal-gate bar)

Subagents

Agent Verdict
parity-checker PAIRED — level-up overlay button removal is behaviorally identical on both platforms (tap-anywhere/backdrop-click, 6s auto-dismiss, back/escape all preserved); engagement-slot changes are parallel; the review-moment sheet's mobile-only scope is a legitimate pre-existing platform-adapter exception (web's engagement slot never supported a review slot type, by architecture)
i18n-syncer IN SYNC — reviewMoment.* keys exist identically in en.json and pt-BR.json with matching interpolation placeholders; old reviewPrompt.* keys and references are fully removed repo-wide
contract-aligner N/A — diff touches no packages/shared/src/types/*, endpoints.ts, or orbit-api DTOs
security-reviewer N/A — diff touches no orbit-api code

Validation

Not run in this session — CI runs Build / Unit Tests / SonarCloud as separate required checks for this PR (skipped per workflow instructions). PR body self-reports: shared 1384 / mobile 929 / web 2105 tests passing, lint/typecheck clean across all 3 workspaces.

Deferred

  • Contract drift / backend hard rules: N/A — no shared Zod types/endpoints or orbit-api DTO changes; the new EngagementPromptKind union member is client-only Zustand shape, never serialized to the API. orbit-api repo not checked out in this job — not verifiable here regardless.

What's good

  • Eligibility logic (isReviewMomentEligible) is a single pure function reused at both arm time and display time — no duplicated logic, no drift risk.
  • trackCompletion() runs before the arm-time eligibility check so the triggering completion counts toward its own milestone.
  • Old mechanism (ReviewReminderCard, reviewPrompt.* keys, reviewReminder slot) is cleanly and completely removed — zero dead references anywhere.
  • The Android tsconfig fix carries a proper WHY comment with an upstream URL and a dedicated regression test.
  • Level-up overlay dismissal behavior (tap, back/escape, auto-dismiss) is preserved identically on both platforms with matching new tests.

Recommendation

Add the FEATURES.md row and fix the two em-dash copy strings (en + pt-BR) before merge — both are small, mechanical fixes, no architectural rework needed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Review prompt upgrade — post-celebration Astra-branded review moment (Android)

1 participant