Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 10 additions & 5 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
# AGENTS.md — OpenStrap `edge`

Reviewer context, verified against code at `kAlgoVersion 47`, schema `v25`,
`0.9.19+50`. Where a source comment disagrees with an implementation, **the
implementation wins** — header comments here go stale (e.g.
Reviewer context. This doc drifts from code between edits — check
`kAlgoVersion` (`lib/compute/derivation_engine.dart`), `schemaVersion`
(`lib/data/db.dart`), and the `version:` line in `pubspec.yaml` directly
rather than trusting a number written here. Where a source comment disagrees
with an implementation, **the implementation wins** — header comments here go
stale (e.g.
`lib/compute/substrate.dart:10-12` still describes a wake-to-wake day model that
`calendarDays()` at `:429` no longer implements; it walks local midnight to
local midnight).
Expand Down Expand Up @@ -48,8 +51,10 @@ unless it is pure orchestration.
- `notify/` — `notification_center.dart` is the **single emitter**;
`fired_keys.dart` is the persistent fire-once guard.
- `coach/` — read-only SQL over allow-listed `v_*` views behind a deny-list guard.
- `ui/` — ~120 files: `ui/design` (design system), `ui/kit/charts.dart`,
`ui/screens/` (shared metric/trend IA).
- `ui2/` — 66 files (`lib/ui` was deleted in the UI rebuild): `ui2/theme.dart`
and `ui2/grammar.dart` (design system), `ui2/charts.dart`, `ui2/screens/`
(shared metric/trend IA), plus `ui2/onboarding/`, `ui2/activity/`,
`ui2/profile/`.
- Also `ai/` (BYOK), `gps/`, `health/` (HealthKit/Health Connect export),
`telemetry/` (opt-in), `widget/` (App-Group snapshot for WidgetKit/watch).

Expand Down
11 changes: 10 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -221,13 +221,22 @@ lib/ble/ Bluetooth + sync
lib/data/ local storage + the repository seam the UI reads from
lib/compute/ runs the analytics pipeline, writes results
lib/state/ AppState, the one source of truth
lib/ui/ every screen
lib/ui2/ every screen
```

Protocol decoding and analytics live in their own repos —
[protocol](https://github.com/OpenStrap/protocol),
[analytics](https://github.com/OpenStrap/analytics).

## Guides

- [`guides/IOS_INSTALLATION.md`](guides/IOS_INSTALLATION.md) — building and installing on an iPhone.
- [`guides/IOS_SIDELOAD.md`](guides/IOS_SIDELOAD.md) — sideloading without a paid developer account.
- [`guides/WATCH_SETUP.md`](guides/WATCH_SETUP.md) — the Apple Watch companion app.
- [`guides/AI_COACH.md`](guides/AI_COACH.md) — bring-your-own-key AI coach, briefings, and journal.
- [`guides/TASKER_INTEGRATION.md`](guides/TASKER_INTEGRATION.md) — buzzing the strap from Tasker/automation.
- [`guides/BUZZ_MEANINGS.md`](guides/BUZZ_MEANINGS.md) — what each buzz pattern means.

## Contributing

Found something broken? Open an issue. Found something broken and fixed it? Even better,
Expand Down
24 changes: 9 additions & 15 deletions lib/gps/route_math.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,17 @@
//
// Everything here is a pure function of its inputs (no DB, no I/O, no clock),
// so it is directly unit-testable and shared by the repository (splits) and the
// UI (zone-coloured polylines). Distances use the haversine great-circle
// formula on WGS84 mean radius; good to well under a metre at running scale.
// UI (zone-coloured polylines). Distance is latlong2's haversine great-circle
// calculator (WGS84 equatorial radius, not our old mean-radius constant — a
// ~0.1% difference, well under GPS fix noise); good to well under a metre at
// running scale.
Comment on lines +6 to +8

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

nitpick: The new header comment misidentifies latlong2's DistanceHaversine radius as the WGS84 equatorial radius; latlong2 uses its own spherical Earth-radius constant, which is neither the WGS84 equatorial radius nor a ~0.1% change from the removed 6371008.8 m constant. This gives maintainers an incorrect basis for interpreting route-distance changes.

Suggested fix: Describe the value generically as latlong2's spherical Earth-radius constant, or document the actual constant and measured percentage difference.

Suggested change
// calculator (WGS84 equatorial radius, not our old mean-radius constant — a
// ~0.1% difference, well under GPS fix noise); good to well under a metre at
// running scale.
// calculator (latlong2's spherical Earth-radius constant, not our old mean-radius
// constant — the difference is well under GPS fix noise); good to well under a metre at
// running scale.


import 'dart:math' as math;

import 'package:latlong2/latlong.dart';

import 'route_models.dart';

const double kEarthRadiusM = 6371008.8; // WGS84 mean radius
const double kMetersPerKm = 1000.0;
const double kMetersPerMile = 1609.344;

Expand Down Expand Up @@ -65,18 +68,9 @@ double? fallbackSpeedMps(RoutePoint? prev, RoutePoint cur) {
}

/// Great-circle distance in metres between two lat/lng points.
double haversineMeters(double lat1, double lng1, double lat2, double lng2) {
const deg2rad = math.pi / 180.0;
final dLat = (lat2 - lat1) * deg2rad;
final dLng = (lng2 - lng1) * deg2rad;
final a = math.sin(dLat / 2) * math.sin(dLat / 2) +
math.cos(lat1 * deg2rad) *
math.cos(lat2 * deg2rad) *
math.sin(dLng / 2) *
math.sin(dLng / 2);
final c = 2 * math.atan2(math.sqrt(a), math.sqrt(1 - a));
return kEarthRadiusM * c;
}
const _distance = DistanceHaversine(roundResult: false);
double haversineMeters(double lat1, double lng1, double lat2, double lng2) =>
_distance.distance(LatLng(lat1, lng1), LatLng(lat2, lng2));

/// Total path length in metres over an ordered list of route points.
/// Implausible segments (a teleport across a recording gap — see
Expand Down
Loading