ci + docs: test gate on PRs, TestFlight install, landing page, contributor on-ramp - #154
Conversation
623 tests existed and nothing ran them on a pull request. The only
workflow in the repo was the tag-triggered release build, so the actual
review gate on contributions was three AI reviewers and no test run.
Adds flutter analyze + flutter test --concurrency=1 on push and PR.
--concurrency=1 is required: the suite runs sqflite_common_ffi against
real database files and parallel workers race on them.
Two things had to be fixed for a first run to be green rather than red,
because a red baseline badge is worse than no badge:
* derivation_pipeline_test hard-failed without whoop_hist.jsonl. That
fixture is a real band capture kept beside the repo rather than in it,
so it is present locally and absent in CI. Those two tests now skip
when it is missing, matching the analytics suite. 623 pass locally.
* eight pre-existing analyze findings. Individually trivial, but they
meant `flutter analyze` had never exited zero:
- theme.dart imported CupertinoPageTransitionsBuilder from
cupertino.dart, which does not declare it. material.dart
re-exports it, and that import was already in scope — so the line
was both redundant and wrong.
- _Stat.valueColor in live_session_screen was never passed by any
of its seven call sites; the value always fell through to the
default. Removed the dead parameter, not the behaviour.
- three underscore-prefixed locals in substrate.dart, renamed.
- one null-aware map entry in a test.
glassBoxReadiness in crossday_pipeline is deliberately NOT migrated. It
is deprecated in favour of readinessComposite, but switching it changes
user-visible scores and needs a kAlgoVersion bump and a release note, so
it stays an explicit open decision with an ignore comment explaining why,
rather than being silently changed to make a linter happy.
The public surface was lagging well behind the app. Install. iOS was documented as "sideload an unsigned IPA", but a public TestFlight beta has been live and open for a while with no cap on testers. That is a normal install with no computer involved, and it was nowhere in the README. Adds it as the primary iOS path, keeps the sideload guide for anyone who prefers it, and drops the stale "sideload only" line. Also flags WHOOP 5 / MG as detected-but-unvalidated, which is the honest status. Landing page. https://openstrap.github.io/edge/ served a page titled "Edge — Legal" — the repo's own homepage link pointed at the privacy policy. Adds a real landing page at docs/index.html (screenshots, both install paths, what the app is and what it deliberately does not claim) and moves the legal index to docs/legal.html, which every legal page now links. Reuses the existing CSS tokens; no framework, no build step. Contributor on-ramp. 53 forks, one regular outside contributor, and no CONTRIBUTING, SECURITY, issue templates or funding config. Adds: - CONTRIBUTING.md, leading with the thing that actually blocks people: which of the three repos a change belongs in. Plus the two rules that matter — never fabricate a number when the input is missing, and cite the published method — and the honest ceilings (PRV not ECG HRV, relative-only SpO2/temp) that read like bugs but are not. - SECURITY.md for private disclosure, scoped to where the data actually is: the phone, the BLE link, the local database. Not a cloud backend, because there isn't one. - Two issue forms. The second, "a metric looks wrong", exists because "it doesn't match the WHOOP app" is the most common report and is not by itself a bug — the form says so up front and asks for the kind of wrong instead. DONATE.md carries the BTC and EVM addresses, with FUNDING.yml pointing at it (GitHub's config takes URLs, not wallet addresses). It says plainly that nothing is gated behind paying and that bug reports from real bands are worth more — which is true, since otherwise there is exactly one person's physiology in the test data.
|
Warning Review limit reached
Next review available in: 45 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (2)
📝 WalkthroughWalkthroughThe PR adds repository contribution, security, funding, issue, and CI configuration; rebuilds the Edge static homepage and legal navigation; and applies targeted Flutter, decoding, UI, and test-fixture maintenance changes. ChangesProject operations and contributor guidance
Static website and legal navigation
Application maintenance and test fixtures
Estimated code review effort: 3 (Moderate) | ~25 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
PR Reviewer Guide 🔍(Review updated until commit 94d04ad)Here are some key observations to aid the review process:
|
PR Code Suggestions ✨Latest suggestions up to 94d04ad Explore these optional code suggestions:
Previous suggestionsSuggestions up to commit d1ac6fa
Suggestions up to commit 2f93bcc
Suggestions up to commit 3ba9b4b
Suggestions up to commit 1190386
|
The first CI run failed, and the failure is worth keeping the note about. `channel: stable` resolved to Flutter 3.44.8 on the runner while local dev is on 3.41.6. CupertinoPageTransitionsBuilder moved between cupertino.dart and material.dart across those versions, so the same theme.dart is analyze-clean on one and five hard errors on the other. I'd "fixed" a local unused-import warning by deleting the cupertino import, which was correct for 3.41.6 and broke the build on 3.44.8. Reverted that import and pinned flutter-version: 3.44.8, with a comment on the import warning the next person not to clean it up without checking the pinned toolchain. This is the same reasoning as the commit-SHA pins for sibling packages in pubspec.yaml: a floating ref means the toolchain changes underneath an already-reviewed commit. CI is now deterministic. Note this leaves local dev on 3.41.6 reporting two warnings that CI does not see. Upgrading local Flutter to the pinned version makes both agree.
|
Persistent review updated to latest commit 1190386 |
There was a problem hiding this comment.
Actionable comments posted: 7
🧹 Nitpick comments (3)
.github/ISSUE_TEMPLATE/wrong_number.yml (1)
39-59: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winCapture the band model for metric reports.
README.md Lines 88-90 state that WHOOP 5.0/MG is experimental while WHOOP 4.0 is validated. Without a required band field, reports cannot distinguish device-specific behavior.
Add a band dropdown, reusing the options from
.github/ISSUE_TEMPLATE/bug_report.yml.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In @.github/ISSUE_TEMPLATE/wrong_number.yml around lines 39 - 59, Add a required band dropdown to the wrong-number issue template near the existing kind and version fields, using the same options and labeling conventions as the band field in bug_report.yml. Preserve the current validations and ensure reporters must select their WHOOP device band.DONATE.md (1)
10-19: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winFix the Markdown heading and fence warnings.
The document jumps from h1 to h3 and both wallet-address fences lack a language, triggering MD001 and MD040.
Proposed fix
-### Bitcoin +## Bitcoin -``` +```text bc1qvtcch38dcwp967ar764uu6eetw7tf907844wfq-### EVM — Ethereum, Base, Arbitrum, Optimism, Polygon
+## EVM — Ethereum, Base, Arbitrum, Optimism, Polygon-
+text
0x8310C89393366b7eBCD47ABa82e1dfB5ECeFFbD9🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@DONATE.md` around lines 10 - 19, Update the Markdown headings in DONATE.md so the Bitcoin section uses the appropriate level without skipping from h1 to h3, and change both wallet-address code fences under the Bitcoin and EVM sections to use the text language identifier. Keep the wallet addresses unchanged.Source: Linters/SAST tools
docs/style.css (1)
216-218: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winScope the landing-page selectors.
The comment says these rules are used only by
index.html, but selectors such as.fineprint,.card, and.pipelineare global whilestyle.cssis shared with legal pages. Add a landing-page body class and prefix these selectors, or split the stylesheet, to prevent cross-page style collisions.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@docs/style.css` around lines 216 - 218, Scope the landing-page selectors in the section beginning with the landing-page comment so they cannot affect legal pages. Add a landing-page class to the index.html body and prefix selectors such as .fineprint, .card, and .pipeline with that class, preserving their existing landing-page styling while leaving shared legal-page rules unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In @.github/ISSUE_TEMPLATE/bug_report.yml:
- Around line 74-80: Update the screenshots textarea description in the bug
report template to explicitly warn that issues are public and reporters must
redact health information and personal identifiers before uploading images.
Replace the current vague redaction wording while preserving the existing field
and validation settings.
In @.github/ISSUE_TEMPLATE/config.yml:
- Around line 2-25: Add a contact_links entry in the config.yml contact_links
list for private vulnerability reporting, using the repository’s GitHub private
security advisory/reporting URL and clearly directing reporters not to open
public issues. Preserve the existing category links and formatting.
In @.github/workflows/test.yml:
- Line 17: Harden the checkout step using actions/checkout@v4 by setting
persist-credentials to false and configure the workflow job’s repository
permissions as read-only. Apply these changes to the checkout and job
permissions configuration without altering the dependency installation,
analysis, or test steps.
In `@docs/index.html`:
- Line 7: Update the homepage description metadata and corresponding visible “No
cloud” claims in docs/index.html to qualify that health data stays off the cloud
or disclose the Firebase crash/performance diagnostics exception. Keep the
wording consistent across the referenced locations and aligned with the
diagnostics disclosure in docs/privacy.html.
In `@docs/legal.html`:
- Line 15: Update the Legal navigation link in legal.html to include
aria-current="page", preserving its existing href and label.
In `@lib/theme/theme.dart`:
- Around line 28-30: Add an explicit package:flutter/cupertino.dart import in
the theme file so CupertinoPageTransitionsBuilder usages resolve, while
retaining the existing material.dart import for other symbols.
In `@SECURITY.md`:
- Around line 42-48: Update the privacy-boundary descriptions in SECURITY.md and
README.md to consistently enumerate all network-capable features, including
optional diagnostics and health-app integrations, alongside legacy import and
the update pointer. Ensure both documents clearly state that opt-in features are
disabled by default and compiled out of store builds, and remove or revise
README.md’s incomplete “only three network calls” wording.
---
Nitpick comments:
In @.github/ISSUE_TEMPLATE/wrong_number.yml:
- Around line 39-59: Add a required band dropdown to the wrong-number issue
template near the existing kind and version fields, using the same options and
labeling conventions as the band field in bug_report.yml. Preserve the current
validations and ensure reporters must select their WHOOP device band.
In `@docs/style.css`:
- Around line 216-218: Scope the landing-page selectors in the section beginning
with the landing-page comment so they cannot affect legal pages. Add a
landing-page class to the index.html body and prefix selectors such as
.fineprint, .card, and .pipeline with that class, preserving their existing
landing-page styling while leaving shared legal-page rules unchanged.
In `@DONATE.md`:
- Around line 10-19: Update the Markdown headings in DONATE.md so the Bitcoin
section uses the appropriate level without skipping from h1 to h3, and change
both wallet-address code fences under the Bitcoin and EVM sections to use the
text language identifier. Keep the wallet addresses unchanged.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: 7e9a54dd-03e0-4637-85cd-5c4733bc9aa9
📒 Files selected for processing (21)
.github/FUNDING.yml.github/ISSUE_TEMPLATE/bug_report.yml.github/ISSUE_TEMPLATE/config.yml.github/ISSUE_TEMPLATE/wrong_number.yml.github/workflows/test.ymlCONTRIBUTING.mdDONATE.mdREADME.mdSECURITY.mddocs/index.htmldocs/legal.htmldocs/notice.htmldocs/privacy.htmldocs/style.cssdocs/terms.htmllib/compute/crossday_pipeline.dartlib/compute/substrate.dartlib/theme/theme.dartlib/ui/activity/live_session_screen.darttest/derivation_pipeline_test.darttest/readiness_flash_test.dart
| ## Where your data actually is | ||
|
|
||
| Worth knowing before you go looking: OpenStrap computes and stores everything | ||
| on-device. There's no account and no server holding your health data. The | ||
| optional companion worker exists for legacy import, an update pointer, and two | ||
| opt-in features that are off by default and compiled out of store builds | ||
| entirely. See [PRIVACY.md](PRIVACY.md). |
There was a problem hiding this comment.
🔒 Security & Privacy | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
printf '\n== SECURITY.md (around cited lines) ==\n'
nl -ba SECURITY.md | sed -n '35,60p'
printf '\n== README.md (around cited lines) ==\n'
nl -ba README.md | sed -n '120,155p'
printf '\n== PRIVACY.md (top and relevant matches) ==\n'
nl -ba PRIVACY.md | sed -n '1,220p'
printf '\n== Search for related terms ==\n'
rg -n --hidden --glob '!**/.git/**' \
-e 'legacy import|update pointer|opt-in feature|store build|compiled out|BYOK|LLM proxy|telemetry|health-upload|health data|network inventory|companion worker|update.*pointer|privacy boundary' .Repository: OpenStrap/edge
Length of output: 232
🏁 Script executed:
#!/bin/bash
set -euo pipefail
printf '\n== SECURITY.md (around cited lines) ==\n'
awk 'NR>=35 && NR<=60 {printf "%4d %s\n", NR, $0}' SECURITY.md
printf '\n== README.md (around cited lines) ==\n'
awk 'NR>=120 && NR<=155 {printf "%4d %s\n", NR, $0}' README.md
printf '\n== PRIVACY.md (top and relevant matches) ==\n'
awk 'NR>=1 && NR<=220 {printf "%4d %s\n", NR, $0}' PRIVACY.md
printf '\n== Search for related terms ==\n'
rg -n --hidden --glob '!**/.git/**' \
-e 'legacy import|update pointer|opt-in feature|store build|compiled out|BYOK|LLM proxy|telemetry|health-upload|health data|network inventory|companion worker|update.*pointer|privacy boundary' .Repository: OpenStrap/edge
Length of output: 24853
Align the privacy boundary wording across SECURITY.md and README.md. README.md’s “only three network calls” line is incomplete; it needs to account for the optional diagnostics and health-app integrations, and the store-build exclusions should be stated consistently in both docs.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@SECURITY.md` around lines 42 - 48, Update the privacy-boundary descriptions
in SECURITY.md and README.md to consistently enumerate all network-capable
features, including optional diagnostics and health-app integrations, alongside
legacy import and the update pointer. Ensure both documents clearly state that
opt-in features are disabled by default and compiled out of store builds, and
remove or revise README.md’s incomplete “only three network calls” wording.
Correcting the previous commit, which pinned 3.44.8. That was the wrong direction and CI caught it. The repo genuinely cannot build on Flutter 3.44.x: phosphor_flutter 2.1.0 extends IconData, which became a `final class` in 3.44, so every widget test fails to compile with The class 'IconData' can't be extended outside of its library because it's a final class. That is a real forward-compatibility problem worth knowing about independently of CI — moving past 3.41.x needs phosphor_flutter bumped or replaced first. Left as-is here rather than bundled into a docs pass. So CI pins 3.41.6, which is what local development actually uses and what the release build produces. With that pin the cupertino import in theme.dart is genuinely redundant (material.dart re-exports the symbol on this version), so it goes back out, with a comment saying what to do if the pin is ever bumped. Local and CI now agree: analyze clean, 623 tests.
|
Persistent review updated to latest commit 3ba9b4b |
CI is green — and it caught a real forward-compat problem on its first runWorth calling out separately from the diff, because it's a finding rather than a change. The repo does not build on current Flutter stable. Every widget test fails to compile on 3.44.8. Local dev and the release build are on 3.41.6, so nothing had surfaced it — this is exactly the class of thing a PR gate exists to find, and it found it within an hour of existing. I've pinned CI to Same reasoning as the commit-SHA pins for sibling packages in Final state — local and CI now agree:
|
The one comment the HN submission got (item 48939059) said the app "doesn't appear to be any Apple Health integration (yet)" and that there's "no background sync on iOS -- you have to open the app to sync." Both are wrong, and the README is why: * HealthKit and Health Connect export has been shipping (health_export.dart, wired through app_state and the profile screen: sleep stages, resting HR, HRV SDNN/RMSSD, respiratory rate, active energy, steps, workouts, idempotent per day). The README did not contain the string "Apple Health" or "HealthKit" anywhere at all. * iOS background sync exists -- a BGProcessingTask, a lighter BGAppRefreshTask, and a separate restore CBCentral that relaunches the app when the band reconnects, plus a foreground service and a 15-minute watchdog worker on Android. Its ONLY mention in the README was a bullet under "What doesn't work", so a reader skimming for it concluded it wasn't there. That second one is the more instructive failure. The honesty framing is worth keeping, but listing genuinely hard work exclusively under its caveat reads as an absence. Now stated under "What works" with the limitation kept immediately below it, sharpened to say what is actually true: the tasks work, iOS decides when they run. Also mentions the local .db export and the smart alarm, neither of which appeared anywhere either.
One more commit: fixing what the HN thread revealedThe HN submission got exactly one comment. It was positive, but it made three claims — and two of them are factually wrong:
That last one is the instructive failure. The honesty framing is a real asset and worth keeping — but listing genuinely hard engineering exclusively under its own caveat reads to a skimmer as an absence. A technically sophisticated reader looked for both features, couldn't find them, and said so publicly on the project's only HN thread. Nobody corrected it, because the submitter wasn't the author ( Now both are under "What works", with the iOS limitation kept immediately below and sharpened to what's actually true: the tasks work, iOS decides when they run. Also added the local |
|
Persistent review updated to latest commit 2f93bcc |
The substantive one: the landing page said "No account, no cloud, nothing to pay", and the README said "the only network calls this app ever makes are three narrow, optional things". Both are wrong, and PRIVACY.md already said so. Anonymous Firebase crash/performance diagnostics are ON BY DEFAULT in GitHub release builds — which is what almost everyone is running right now, since store builds don't exist yet. They're switchable off in-app, absent entirely from App Store/Play Store builds, and never carry health data. Separately, opt-in health-data contribution does upload the local database when enabled. Neither appeared in the README's list of network calls. The health-data claim was always true and stays: nothing sends your health data anywhere unless you turn it on. But "no cloud", unqualified, is the kind of thing this project exists not to do — the whole pitch is that the numbers admit what they don't know. Overclaiming on privacy while doing that would be indefensible, and it's the one claim a hostile reader would check first. So: * Landing page hero says "no server that ever receives your health data" instead of "no cloud", with the diagnostics exception stated in the card that makes the claim, linked to the full policy. * README replaces the "three narrow things" line with all five network paths, each marked required/optional and store-vs-GitHub. * SECURITY.md states the same boundary exactly, rather than "computes and stores everything on-device". Also from the review: * Both issue forms now say the issue is PUBLIC and ask for health data, dates and identifiers to be redacted before uploading screenshots. This is a health app; "redact whatever you want to" wasn't good enough. * Issue chooser gets a private security-reporting link, so the router doesn't send every category to a public issue while SECURITY.md says not to file security problems publicly. * Workflow: permissions: contents: read + persist-credentials: false. * aria-current="page" on each legal page's own nav link. Not applied — CodeRabbit flagged the removed cupertino import in theme.dart as critical, claiming material.dart no longer exports CupertinoPageTransitionsBuilder. That's true on Flutter 3.44 and false on 3.41.6, which is what this repo pins and builds against. CI is green on the pinned toolchain; re-adding the import would break it.
|
Persistent review updated to latest commit d1ac6fa |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@README.md`:
- Around line 161-165: Update the README privacy comparison so the BYOK AI
assistant entry explicitly acknowledges that prompts may include health-related
data, and revise the Health-data contribution statement to claim only that it is
the sole feature uploading the local database wholesale.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: 846febe5-832c-4d1b-8a23-4e97ea8fefb8
📒 Files selected for processing (10)
.github/ISSUE_TEMPLATE/bug_report.yml.github/ISSUE_TEMPLATE/config.yml.github/ISSUE_TEMPLATE/wrong_number.yml.github/workflows/test.ymlREADME.mdSECURITY.mddocs/index.htmldocs/legal.htmldocs/style.csslib/theme/theme.dart
🚧 Files skipped from review as they are similar to previous changes (8)
- docs/legal.html
- .github/ISSUE_TEMPLATE/config.yml
- .github/ISSUE_TEMPLATE/wrong_number.yml
- SECURITY.md
- lib/theme/theme.dart
- .github/workflows/test.yml
- docs/index.html
- docs/style.css
CodeRabbit triage — 5 applied, 1 rejectedApplied
The "No cloud" one deserves calling out, because CodeRabbit caught a genuine honesty failure and it's exactly the kind this project can least afford. The landing page said "No account, no cloud, nothing to pay." The README said "the only network calls this app ever makes are three narrow, optional things." Both are wrong — and
Anonymous Firebase crash/performance diagnostics are on by default in GitHub release builds — which is what essentially every current user is running, since store builds don't exist yet. Never health data, absent from store builds, switchable off. Separately, opt-in health-data contribution does upload the local DB when enabled. Neither appeared in the README's list. The health-data claim was always true and stands: nothing sends your health data anywhere unless you turn it on. But "no cloud" unqualified is precisely the kind of overclaim this project exists not to make. The entire pitch is metrics that admit what they don't know — overclaiming on privacy while doing that would be indefensible, and it's the first claim a hostile reader checks. Hero now reads "no server that ever receives your health data", with the diagnostics exception stated in the card that makes the claim. README lists all five network paths, each marked required/optional and store-vs-GitHub. Rejected
CI: ✅ analyze clean, 623 tests. |
Second CodeRabbit pass on the privacy rewrite, and it caught a real soft spot in my own wording. The BYOK AI assistant bullet said only "your key, your account, prompts go to whoever you chose" — which quietly implies the prompts are about health rather than made of it. They are made of it: coach_prompt.dart hands the model read access to v_metric (rhr, rmssd, sdnn, readiness, strain, sleep, and the rest), because that is the only way it can answer "why is my recovery low". Anyone enabling that is sending their metrics to OpenAI or whoever they configured, and the README should say so in those words. Also tightened the health-data-contribution line. It claimed to be "the only thing here that does", which read as "the only thing that sends health data" when what is actually true is narrower: it's the only thing that sends the whole database rather than a slice. The AI assistant sends a slice. Separately, added a band dropdown to the wrong-number issue form, matching the bug form. WHOOP 5.0/MG feeds a thinner record than 4.0, so a metric can be genuinely wrong on one and fine on the other — without that field the first reply is always "which band?".
|
Persistent review updated to latest commit 94d04ad |
User description
Part of a pass over the org's public surface. Sibling PRs: OpenStrap/protocol#17, OpenStrap/analytics#28, OpenStrap/.github, OpenStrap/backend.
Two commits, reviewable separately.
1.
ci:run analyze + the full suite on every PR623 tests existed and nothing ran them on a pull request. The only workflow was the tag-triggered release build, so the actual gate on incoming contributions was three AI reviewers and no test run.
Adds
flutter analyze+flutter test --concurrency=1on push and PR.--concurrency=1is required — the suite runssqflite_common_ffiagainst real database files and parallel workers race on them.Getting the first run green (a red baseline badge is worse than no badge) needed:
derivation_pipeline_testhard-failed withoutwhoop_hist.jsonl. That fixture is a real band capture kept beside the repo rather than in it — present locally, absent in CI. Those two tests now skip when it's missing, matching the analytics suite. 623 still pass locally.flutter analyzehad never exited zero:theme.dartimportedCupertinoPageTransitionsBuilderfromcupertino.dart, which doesn't declare it.material.dartre-exports it and was already imported — the line was both redundant and wrong._Stat.valueColorinlive_session_screenwas never passed by any of its seven call sites; the value always fell through to the default. Removed the dead parameter, not the behaviour.substrate.dart, renamed.glassBoxReadinessis deliberately not migrated. It's deprecated in favour ofreadinessComposite, but switching it changes user-visible scores and needs akAlgoVersionbump plus a release note. It stays an explicit open decision with anignorecomment explaining why, rather than being silently changed to satisfy a linter.2.
docs:TestFlight, landing page, contributor on-rampInstall. The README documented iOS as "sideload an unsigned IPA" — but a public TestFlight beta has been live and open with no tester cap, and it wasn't mentioned anywhere. That's a normal install with no computer involved:
Now the primary iOS path; the sideload guide stays for anyone who prefers it. Drops the stale "sideload only" line and flags WHOOP 5 / MG as detected-but-unvalidated, which is the honest status.
Landing page.
https://openstrap.github.io/edge/served a page titled "Edge — Legal" — the repo's homepage link pointed at the privacy policy. Adds a real landing page atdocs/index.htmland moves the legal index todocs/legal.html, which every legal page now links. Reuses the existing CSS tokens; no framework, no build step, light and dark.Contributor on-ramp. 53 forks, one regular outside contributor, and no
CONTRIBUTING,SECURITY, issue templates or funding config. Adds all four.CONTRIBUTING.mdleads with what actually blocks people — which of the three repos a change belongs in — then the two rules that matter (never fabricate a number when the input is missing; cite the published method) and the honest ceilings (PRV not ECG-grade HRV, relative-only SpO₂/temp) that read like bugs but aren't.Two issue forms. The second, "a metric looks wrong", exists because "it doesn't match the WHOOP app" is the most common report and isn't by itself a bug — the form says so up front and asks what kind of wrong instead.
DONATE.mdcarries the BTC and EVM addresses, withFUNDING.ymlpointing at it (GitHub's config takes URLs, not wallet addresses). It states plainly that nothing is gated behind paying and that bug reports from real bands are worth more — which is true, since otherwise there's exactly one person's physiology in the test data.Verification
flutter analyze→ No issues found!flutter test --concurrency=1→ 623 passPR Type
Enhancement, Bug fix, Documentation, tests
Description
Adds GitHub Actions CI workflow running
flutter analyze+flutter teston every PRFixes eight pre-existing analyzer errors (dead import, dead parameter, underscore-prefixed locals, null-aware map entry) to get a green baseline
Adds
CONTRIBUTING.md,SECURITY.md,DONATE.md, GitHub issue templates, and funding config for contributor on-rampRewrites
docs/index.htmlinto a real landing page with install CTAs, screenshots, and feature cards; extracts legal index todocs/legal.htmlDiagram Walkthrough
File Walkthrough
3 files
New CI workflow: analyze and test on every PRAdd GitHub funding config pointing to DONATE.mdAdd issue template config with contact links11 files
Add explanatory comment and suppress deprecated_member_use warningNew contributor guide: repo split, rules, and workflowAdd donation page with BTC and EVM addressesAdd security policy with private reporting instructionsAdd CI badge, TestFlight install section, and contribution linksAdd structured bug report issue templateAdd structured wrong-metric issue templateExtract legal index page from former index.htmlAdd Legal nav link to site headerAdd Legal nav link to site headerAdd Legal nav link to site header4 files
Rename underscore-prefixed locals to fix analyzer warningsRemove redundant and incorrect cupertino.dart importRemove dead valueColor parameter never passed by call sitesFix null-aware map entry analyzer warning in test helper1 files
Skip fixture-dependent tests when whoop_hist.jsonl is absent2 files
Rewrite as real landing page with install CTAs and feature cardsAdd landing page styles: hero, cards, shots, CTA, addrSummary by CodeRabbit
New Features
Improvements
Documentation