CueSheetEnricher interface, canonical Direction enum, and tier-0 GpxCueEnricher (#26) #79
No reviewers
Labels
No labels
area:companion
area:docs
area:shared
area:tooling
area:watchapp
blocker
kind:chore
kind:feature
kind:spike
kind:test
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
robert/PedalPebble!79
Loading…
Reference in a new issue
No description provided.
Delete branch "area/cue-sheet-enricher-interface"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Closes #26.
Scope note
Read the issue body plus its 2026-09-01 "four tiers, and cue confidence" update before starting — that update materially changes scope from a single-backend interface to a four-tier fallback chain with per-cue tier/confidence, and this PR follows the update, not the original text.
What this builds
Direction(core/route/enrich/Direction.kt) — the canonical turn vocabulary, adopted from the komoot BLE Connect spec (github.com/palto42/BLEConnect) per the issue. Every value from the spec's Direction table is represented except the explicitly-reserved/future-extension codes;bleConnectCodeis kept only as a traceability breadcrumb (this project never speaks BLE Connect's wire protocol).DirectionVocabulary— the single place a backend's vocabulary is translated intoDirection(the issue's "mapping lives in exactly one place" criterion). ShipsfromGpxCueTexttoday for tier 0's text (D58/D59: bikerouter.de/BRouter emit "left, 80 m"-shaped text, English and German, never a street name); #27/#28 are expected to add their ownfromXxxfunctions to this same object rather than inventing private tables.CueSheetEnricher(core/route/enrich/CueSheetEnricher.kt) —EnrichmentTier,Cue(polyline index, direction, street name, distance-along-route, plus which tier produced it),CueEnrichmentSource,CueSheetResult, theCueSheetEnricherinterface itself, andTieredCueSheetEnricher, which orchestrates tier0..tier3 in order — enforced by the constructor's fixed four slots, not by caller discipline over aList— stopping at the first non-empty result and recording which tier won.GpxCueEnricher(#63, tier 0) — implemented, not stubbed, because it fell out of the interface work with time to spare. Reads<rtept>/<trkpt>name/desctext, classifies it, and locates each cue onto the already-simplifiedGpxRoutepolyline (#24) by forward-only, segment-interpolated projection (RouteGeodesy.locateAlongPolyline) rather than nearest-vertex snapping — RDP simplification can and does drop the exact point a cue was anchored to, and a naive nearest-point search breaks on out-and-back/figure-eight routes.streetNameis alwaysnull(D58: tier 0 never has one); text the vocabulary doesn't recognise is dropped, never guessed (FR-N17).Deliberately not built here
BRouterEnricher(#27),MatchingEnricher(#28),GeometryEnricher(#29) — separate issues, separate PRs, no network/AIDL/BRouter dependency introduced by this PR.TieredCueSheetEnricheracceptsnullfor any unwired tier, so the chain is honest about only having tier 0 today rather than carrying fake stub implementations.Known gap, flagged rather than hidden
GpxCueEnricheronly covers D59's plain-text encoding, not the other seven GPX cue encodings D59 catalogued (alignment-keyed, vendor<extensions>, XML-comment-hiddentimode=4, icon-id-only). That's real #63 scope. The test fixture (bikerouter-style-cues.gpx) is hand-built to match D58/D59's documented text shape rather than a scraped live export — #38's "real fixtures" principle is a gap #63's own PR should close once a live bikerouter.de sample is available.Where it lives, and why
companion/core/.../route/enrich/— inside:companion:core(pure JVM) rather than:companion:route(an Android library needing AGP/SDK), so it's unit-testable in a sandbox with no Android SDK. Package path still satisfies the issue's.../route/enrich/...file location.Testing
./gradlew :companion:core:test --no-configuration-cache— 27 new tests across 5 spec classes (DirectionVocabularyTest,RouteGeodesyTest,CueSheetEnricherTest,GpxCueEnricherTest, plus the existing suite), all green.--no-configuration-cacheis needed in this sandbox because of a headless-JDK/toolchain quirk unrelated to this change; plain./gradlew :companion:core:testshould work in a normal dev environment or CI.https://claude.ai/code/session_01DAoXbRmJUf2uxNYBfdAXPt