Skip to content

feat(sleep): add a sleep planner card (tonight's target at three goals and the bedtime each implies) - #2819

Open
LeonardSEO wants to merge 1 commit into
ryanbr:mainfrom
LeonardSEO:feat/sleep-planner
Open

LeonardSEO wants to merge 1 commit into
ryanbr:mainfrom
LeonardSEO:feat/sleep-planner

Conversation

@LeonardSEO

Copy link
Copy Markdown

What this PR does

Adds a Sleep planner card to the Sleep tab on Android and macOS/iOS: tonight's sleep target at three goals (70 / 85 / 100 % of tonight's need), the time in bed each one takes at the user's typical efficiency, and the bedtime that implies for the next wake.

  • Tonight's need = the base need and debt the existing Hours-vs-Needed figures use, minus today's naps. Naps only repay debt, so they never push tonight below the base need.
  • Wake time = the armed smart alarm's next fire (through the same resolver the strap alarm is armed from), else last night's wake, else 07:00. The card names which one it used.
  • Time in bed = target / median efficiency of the last 14 nights (clamped to 50-100 %). With no efficiency history it equals the target, so no awake allowance is invented.
  • No plan until there are three consecutive nights with sleep.
  • Pure math in SleepPlanner (StrandAnalytics) with a Kotlin twin and mirrored fixtures. Display-only: nothing feeds a score, a baseline or a stored value.
  • A new reorderable Sleep section with the raw key sleepPlanner on both platforms (not in the .noopbak whitelist, like the other section keys).

The 70/85/100 ladder and the three-night gate follow the shape of the official app's sleep planner (seen in its shipped resources; facts only, no code or strings). The goal names are NOOP's own: Minimum / Solid / Full.

Type of change

  • New feature

How it was tested

  • SleepPlannerTests / SleepPlannerTest (same fixtures on both platforms: three-night gate, nap credit only repaying debt, efficiency median and clamp, bedtime wrap past midnight); SleepLayoutPrefsTests / SleepLayoutPrefsTest and SleepSectionReorderTest updated for the new section.
  • swift test in Packages/StrandAnalytics: 2149 tests pass.
  • ./gradlew testFullDebugUnitTest: 6697 tests, all pass apart from the 2 RecoveryDriversTest half-tie cases that fail the same way on unmodified main.
  • Tools/i18n_audit.py --ci, Tools/doc_comment_lint.py, docs/protocol-examples checks and Tools/parity_ledger.py --refresh-derived (derived snapshots included): pass.
  • Tools unit tests, the parity acceptance suite and the R-R contract: pass apart from the 4 test_check_source_references cases (/var vs /private/var temp path on macOS) that fail the same way on unmodified main.
  • Apple: the macOS app (Strand) builds with this change on my development branch; StrandTests and the iOS target were not run locally for this branch. app-build.yml covers both.

Checklist

  • Swift package tests pass for any package I touched
  • Android unit tests pass if I touched android/ (apart from the 2 RecoveryDriversTest half-tie cases that fail the same way on unmodified main)
  • No new build warnings introduced (Android: none; Apple warnings not checked per branch)
  • UI changes use only StrandDesign / Palette / Metrics tokens
  • No hardcoded hex frame bytes; protocol facts live in the schema / decoders
  • Follows the conventions in docs/CONTRIBUTING.md
  • I did not commit generated output (Strand.xcodeproj/) or any secrets/keystores

Related issues

None.

🤖 Generated with Claude Code

…time each implies

Pure math in StrandAnalytics SleepPlanner with a Kotlin twin and mirrored fixtures. A new reorderable Sleep section on Android and Apple. Display-only.
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.

1 participant