Skip to content

plan 0016 (1/3): device sync foundations — stop tracks that can never sync - #381

Closed
TheAngryRaven wants to merge 4 commits into
BETAfrom
claude/device-sync-foundations
Closed

plan 0016 (1/3): device sync foundations — stop tracks that can never sync#381
TheAngryRaven wants to merge 4 commits into
BETAfrom
claude/device-sync-foundations

Conversation

@TheAngryRaven

@TheAngryRaven TheAngryRaven commented Aug 5, 2026

Copy link
Copy Markdown
Owner

Summary

First of three PRs building the rename-on-connect flow (plan 0016). This one is all model and bug fixes, no UI — the wizard (#385) and the on-connect prompts (#386) sit on top.

Merge order: this → #385#386. All three target BETA independently (no GitHub stack). The branches are chained, so the later two currently show this PR's commits as well; each diff shrinks as the one before it lands.

The on-device course creator writes /TRACKS[/SPRINT]/N260803_1432.json. Renaming that has to happen here, and the new name has to be written back, or the "please name this" prompt fires on every connect. Designing for that turned up four existing ways to produce a track that can never reach synced — the same failure, reached without any of the new code:

  1. buildTrackJsonForUpload emitted a bare JSON array. The firmware parses an array, but its array branch (BirdsEye/sd_functions.ino:475-484) blanks longName/shortName/defaultCourse, and every course falls back to lengthFt = 0 (:507). lengthFt is what CourseDetector ranks courses by — so a track uploaded from this app could never be course-detected and dropped straight to Lap Anything, and the blank shortName reached the DOVEX header's short_name column. The two course-level writers in DeviceTracksTab.tsx hand-rolled the same array.
  2. parseDeviceCourseJson discarded longName/shortName.
  3. handleDownloadToApp never passed a shortName to addTrack, and buildMergedTrackList skips app tracks that have none (if (!sn) continue) — so every downloaded track was invisible to the merge forever.
  4. Identity was confused with location. A device-authored file lives at N260803_1432.json but declares shortName: "08031432" — 8 chars, chosen by the firmware author precisely because that's this app's Track.shortName budget (BirdsEye/course_creator.h:36-57). The merge keyed on the filename, so an imported track could never match the file it came from.

No firmware changes, and no capability gate. The firmware has parsed the object track format since well before any shipped release (field units are 3.0.1/3.1.0) and reads longName, shortName, defaultCourse, type and per-course lengthFt (sd_functions.ino:449-507). Switching the writer asks nothing new of any device in the field.

New pure modules

Test env is node with no testing-library — a dialog can't be rendered — so the whole decision surface lives outside the component:

Module Owns
deviceGeneratedNames.ts Recognising N{YYMMDD}_{HHMM} / MMDDHHMM, with date + time validated so a real name that looks the part isn't treated as a placeholder
deviceSyncPlan.ts What's offered, in which direction, and what's refused
deviceSyncNames.ts Name-edit rules and the save gate
deviceSyncOps.ts The ordered operation list

Rows that can never converge are refused, not retriedmixed_kind, too_many_courses (past the firmware's MAX_LAYOUTS, whose parser silently ignores the tail), and sprint_unsupported (native IPC drops the kind arg). Each would otherwise report a difference on every connect forever. Not trimmed to fit — dropping a user's courses to turn a checkmark green is the worse failure, and truncation is explicitly deferred per the owner.

Ordering is the load-bearing part. Put before delete, so a failure between them leaves the track on the card twice rather than nowhere. Device before app, so a failure after the write leaves a correctly-named file the next connect offers as a plain download, instead of stranding a renamed app track beside its old device file. FAT is case-insensitive, so a case-only filename change is not a rename.

Related Issues

Builds on #380 (merged). Followed by #385 and #386.

Type of Change

  • Bug fix
  • New feature
  • Refactor / reusability improvement
  • Documentation

Checklist

  • bun run lint passes
  • bun run typecheck passes
  • bun run test:run passes (2663 tests, 186 files)
  • bun run build succeeds
  • Feature works offline (no new network calls)
  • Docs updated — docs/plans/0016-device-track-sync-rename.md, CHANGELOG.md

Notes for Reviewers

Two tests were verified to actually bite, by breaking the fix and watching them fail:

  • Reverting the identity rule makes the round-trip report 2 merged entries instead of 1 — literally the app_only/device_only split that made the prompt re-fire.
  • Dropping shortName from the stored track makes both settle tests report device_only.

That mattered, because my first draft of one of them was vacuous: it derived its input from the value under test and passed either way. It now spells the expectation out literally. Worth knowing since the same class of thing is how bug 1 survived review — a test named "emits a JSON array of courses (not a wrapping object)" had pinned the lossy shape as the contract. That test is replaced.

Two things I'd flag rather than have you find:

  • too_many_courses is a real skip, not a no-op. If you have a track with >10 courses it will now be reported as un-syncable rather than silently half-written. That's the deliberate reading of "don't truncate yet" — say so, don't guess. Happy to change the shape once you've decided.
  • The native (Tauri) transport still drops the kind argument on get/put/delete. I guarded around it (sprint rows are skipped there) rather than fixing it, since it's tracked as the plan 0015 Android IPC follow-up.

claude added 4 commits August 5, 2026 05:51
buildTrackJsonForUpload emitted a bare JSON array of courses. The firmware
parses that — but its array branch (sd_functions.ino parseTrackFile) blanks
longName, shortName and defaultCourse, and every course falls back to
lengthFt = 0. lengthFt is what CourseDetector ranks courses by, so a track
uploaded from this app could never be course-detected and dropped straight to
Lap Anything, and the blank shortName reached the DOVEX header's short_name
column.

Emit the object form instead — the same shape the app's own track files and
the on-device course creator already write, and one the firmware has parsed
since well before any shipped release, so no version gate is needed.

Also add parseDeviceTrackFile(), which keeps the wrapper's longName/shortName/
type/defaultCourse rather than discarding them; parseDeviceCourseJson stays as
a thin wrapper over it for the callers that only want courses. The rename flow
needs longName, and needs shortName because for a device-authored track the
FILENAME is the 12-char longName (N260803_1432.json) while the 8-char
shortName the sync merge keys on lives inside the file.

The old "emits a JSON array of courses (not a wrapping object)" test asserted
the lossy shape as the contract, which is how this survived review; it is
replaced with assertions on the metadata the device actually consumes.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ESkRRtF4vRrANPL6huSgmD
A track the on-device course creator wrote is stored at N260803_1432.json but
declares shortName "08031432" — 8 characters, chosen by the firmware precisely
because that is this app's Track.shortName budget and the key its sync merge
uses. buildMergedTrackList keyed on the FILENAME instead, so a track imported
from the device could never be matched to the file it came from: it stayed
"device_only" forever and the sync kept re-offering it.

Separate the two concepts. DeviceTrackFile.shortName is now the identity (the
declared shortName, falling back to the filename base only for legacy
bare-array files that declare nothing), and the new fileName / deviceFileName
carry the location. deviceTrackFileFrom() owns that rule so it is unit-tested
rather than buried in the tab, and every write path now targets the real file
instead of `shortName + ".json"` — which would otherwise orphan the original
and leave two copies on the card.

Also fixes the other half of the same nag: handleDownloadToApp never passed a
shortName to addTrack, and buildMergedTrackList skips app tracks that have
none, so downloaded tracks were invisible to the merge whatever the key was. It
now carries the shortName over and names the track from the file's longName.

The two course-level writers went through rebuildDeviceTrackJson so editing one
course stops stripping the file's wrapper metadata and resetting every lengthFt
— the same loss the bare-array uploader caused, reached from a different button.

Verified by reverting the identity rule and watching the round-trip test report
2 merged entries instead of 1 — literally the app_only/device_only split that
made the prompt re-fire. The first draft of that test derived its input from the
value under test and passed either way; it now spells the expectation out.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ESkRRtF4vRrANPL6huSgmD
Four modules, all Arduino-free pure logic with no React, because the test
environment is "node" with no testing-library — a dialog cannot be rendered, so
anything worth asserting has to live outside the component.

- deviceGeneratedNames: recognises the on-device course creator's
  N{YYMMDD}_{HHMM} names and MMDDHHMM short names. The date and time parts are
  validated, so a real name that merely looks the part isn't mistaken for a
  placeholder and the user pushed to rename something they already named.

- deviceSyncPlan: decides what a sync would offer and in which direction.
  Synced tracks are dropped; app tracks the user didn't create are never pushed
  (the two we ship are reference data, not "unknown tracks"); a mismatch uploads
  the app's version after importing any course walked on the device.
  Crucially it also refuses to offer rows that could never converge — mixed
  circuit+sprint tracks, tracks past the firmware's MAX_LAYOUTS (whose tail its
  parser silently ignores, so the file can never read back as written), and
  sprint tracks on a transport that can't reach /TRACKS/SPRINT. Each of those
  would otherwise report a difference on every connect forever. They are
  surfaced with a reason rather than trimmed to fit: dropping a user's courses
  to turn a checkmark green is the worse failure.

- deviceSyncNames: the edit rules and the save gate. A short name follows the
  long name until the user takes it over, and editing the long name takes it
  back; a course name follows its track's name the same way. Track names are
  required for both kinds — a venue is permanent. Course names are required for
  circuit only: a sprint venue re-lays its course every event, so the date it
  was walked genuinely is the most useful label.

- deviceSyncOps: the ordered operation list. Put before delete, so a failure
  between them leaves the track on the card twice rather than nowhere; device
  before app, so a failure after the write leaves a correctly-named file the
  next connect offers as a plain download, instead of stranding a renamed app
  track beside its old device file. FAT is case-insensitive, so a case-only
  filename change is not a rename — deleting "the old file" would delete the one
  just written.

The load-bearing tests replay a plan back through deviceTrackFileFrom and
buildMergedTrackList and assert "synced". If that ever fails, the on-connect
prompt re-fires on every connect, which is the whole thing this is avoiding.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ESkRRtF4vRrANPL6huSgmD
Captures why the sync path had four separate ways to produce a track that could
never reach "synced", the identity-vs-location split that fixes the worst of
them, why operation order (put before delete, device before app) is the
load-bearing part, and the decisions taken with the owner — including the ones
about what NOT to build: no truncation, no firmware capability layer, no new
opcodes.

Also records that no capability gate is needed here, with the evidence: the
firmware has parsed the object track format since before any shipped release.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ESkRRtF4vRrANPL6huSgmD
@cloudflare-workers-and-pages

Copy link
Copy Markdown

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Preview URL Updated (UTC)
✅ Deployment successful!
View logs
lapwing 744ac9d Commit Preview URL

Branch Preview URL
Aug 05 2026, 06:14 AM

@supabase

supabase Bot commented Aug 5, 2026

Copy link
Copy Markdown

This pull request has been ignored for the connected project tdxloldxzvnzdivdazzd because there are no changes detected in supabase directory. You can change this behaviour in Project Integrations Settings ↗︎.


Preview Branches by Supabase.
Learn more about Supabase Branching ↗︎.

@github-actions

github-actions Bot commented Aug 5, 2026

Copy link
Copy Markdown

Coverage Summary

Lines: 57.93% (7351/12688) · Statements: 57.1% · Functions: 54.61% · Branches: 55.04%

Per-file coverage
File Lines Functions Branches
src/components/admin/supportAttachment.ts 0% 0% 0%
src/components/map/positionArrowMarker.ts 0% 0% 0%
src/components/video-overlays/dataSourceResolver.ts 85.07% 71.42% 80.82%
src/components/video-overlays/overlayUtils.ts 100% 100% 100%
src/components/video-overlays/registry.ts 100% 100% 100%
src/components/video-overlays/sectorUtils.ts 94.73% 100% 84.37%
src/components/video-overlays/themes.ts 100% 100% 100%
src/components/video-overlays/types.ts 100% 100% 100%
src/hooks/use-mobile.tsx 0% 0% 100%
src/hooks/use-toast.ts 0% 0% 0%
src/hooks/useAuth.ts 100% 100% 100%
src/hooks/useDataLoader.ts 14.11% 20% 17.02%
src/hooks/useDocumentHead.ts 0% 0% 0%
src/hooks/useEngineManager.ts 0% 0% 0%
src/hooks/useFileManager.ts 0% 0% 0%
src/hooks/useFirmwareUpdate.ts 0% 0% 0%
src/hooks/useKartManager.ts 100% 100% 100%
src/hooks/useLapManagement.ts 0% 0% 0%
src/hooks/useLapOverlays.ts 0% 0% 0%
src/hooks/useLapSnapshots.ts 0% 0% 0%
src/hooks/useNativeFirmwareUpdate.ts 0% 0% 0%
src/hooks/useNoteManager.ts 0% 0% 0%
src/hooks/useOnlineStatus.ts 0% 0% 0%
src/hooks/usePlayback.ts 0% 0% 0%
src/hooks/useReferenceLap.ts 0% 0% 0%
src/hooks/useSessionData.ts 0% 0% 0%
src/hooks/useSessionMetadata.ts 0% 0% 0%
src/hooks/useSettings.ts 0% 0% 0%
src/hooks/useSetupManager.ts 0% 0% 100%
src/hooks/useSimPlayback.ts 0% 0% 0%
src/hooks/useStripePrices.ts 0% 0% 0%
src/hooks/useSubscription.ts 0% 0% 0%
src/hooks/useTemplateFields.ts 0% 0% 0%
src/hooks/useTemplateManager.ts 0% 0% 0%
src/hooks/useTrackEditorForm.ts 0% 0% 0%
src/hooks/useVehicleManager.ts 0% 0% 100%
src/hooks/useVideoSync.ts 0% 0% 0%
src/hooks/useWakeLock.ts 0% 0% 0%
src/hooks/useWaybackImagery.ts 0% 0% 0%
src/lib/test/idb.ts 100% 100% 100%
src/lib/aimParser.ts 96.21% 100% 83.05%
src/lib/alfanoParser.ts 93.44% 100% 75.66%
src/lib/appActivity.ts 0% 0% 100%
src/lib/billing.ts 97.36% 100% 98.21%
src/lib/billingClient.ts 0% 0% 0%
src/lib/ble/test/mockBle.ts 96% 90% 50%
src/lib/ble/battery.ts 93.33% 100% 87.5%
src/lib/ble/connection.ts 0% 0% 0%
src/lib/ble/dfu/dfuPackage.ts 96.66% 100% 81.25%
src/lib/ble/dfu/dfuTypes.ts 100% 100% 100%
src/lib/ble/dfu/firmwareImage.ts 100% 100% 100%
src/lib/ble/dfu/firmwareManifest.ts 96.92% 92.85% 93.18%
src/lib/ble/dfu/firmwareUpdateError.ts 100% 100% 100%
src/lib/ble/dfu/index.ts 100% 100% 100%
src/lib/ble/dfu/version.ts 96.77% 100% 83.33%
src/lib/ble/fileTransfer.ts 90.69% 95% 72.91%
src/lib/ble/firmwareCrc.ts 100% 100% 100%
src/lib/ble/firmwareUpload.ts 90.62% 88% 84.31%
src/lib/ble/format.ts 100% 100% 100%
src/lib/ble/index.ts 100% 100% 100%
src/lib/ble/internal.ts 100% 100% 50%
src/lib/ble/settings.ts 93.6% 100% 85.29%
src/lib/ble/trackOpcodes.ts 100% 100% 100%
src/lib/ble/trackSync.ts 89.89% 90.9% 72.72%
src/lib/ble/types.ts 100% 100% 100%
src/lib/bleDatalogger.ts 100% 100% 100%
src/lib/blogPosts.ts 100% 100% 97.22%
src/lib/brakingZones.ts 97.14% 100% 86.11%
src/lib/browserCompat.ts 0% 0% 0%
src/lib/buildInfo.ts 100% 100% 100%
src/lib/canvas2d.ts 100% 100% 91.66%
src/lib/channels.ts 100% 100% 84.61%
src/lib/chartAxis.ts 98% 100% 82.92%
src/lib/chartColors.ts 100% 100% 100%
src/lib/chartUtils.ts 100% 100% 97.05%
src/lib/contactMessage.ts 47.61% 50% 43.75%
src/lib/courseDetection.ts 97.34% 100% 81.11%
src/lib/courseLineStyle.ts 100% 100% 100%
src/lib/courseSectors.ts 100% 100% 94.73%
src/lib/datalogParser.ts 83.56% 80% 81.81%
src/lib/db/index.ts 0% 0% 0%
src/lib/db/submissionMaterialize.ts 100% 100% 97.5%
src/lib/db/supabaseAdapter.ts 0% 0% 0%
src/lib/db/types.ts 100% 100% 100%
src/lib/dbUtils.ts 76.23% 80% 17.2%
src/lib/debugConsole.ts 57.74% 61.11% 47.72%
src/lib/deviceGeneratedNames.ts 100% 100% 100%
src/lib/deviceSettingsSchema.ts 93.33% 100% 96.42%
src/lib/deviceSyncNames.ts 100% 100% 100%
src/lib/deviceSyncOps.ts 100% 100% 92.85%
src/lib/deviceSyncPlan.ts 100% 100% 96.96%
src/lib/deviceTrackSync.ts 100% 100% 96.94%
src/lib/doveParser.ts 89.6% 72.72% 77.27%
src/lib/dovexParser.ts 88.31% 100% 82.85%
src/lib/driverProfileGroups.ts 100% 100% 83.33%
src/lib/emailValidation.ts 100% 100% 100%
src/lib/engineStorage.ts 100% 75% 100%
src/lib/engineUtils.ts 100% 100% 91.66%
src/lib/fieldResolver.ts 100% 100% 83.33%
src/lib/fileBrowserTree.ts 98.87% 97.5% 89.36%
src/lib/fileLoadingState.ts 100% 100% 100%
src/lib/fileStorage.ts 82.79% 78.12% 72.22%
src/lib/fnv1a.ts 100% 100% 100%
src/lib/garageEvents.ts 100% 100% 100%
src/lib/gforceCalculation.ts 100% 100% 97.22%
src/lib/ggDiagram.ts 100% 100% 94.73%
src/lib/gps/customGps.ts 100% 100% 82.05%
src/lib/gps/dovepWriter.ts 100% 100% 92%
src/lib/gps/gpsFix.ts 100% 100% 100%
src/lib/gps/index.ts 100% 100% 100%
src/lib/gps/observationSample.ts 100% 100% 100%
src/lib/gps/realtimeTimer.ts 90.07% 100% 76.04%
src/lib/gps/sessionGate.ts 100% 100% 100%
src/lib/gpsQualityFilter.ts 100% 100% 96.77%
src/lib/graphPrefsStorage.ts 100% 100% 100%
src/lib/i18n/config.ts 100% 100% 100%
src/lib/i18n/format.ts 100% 100% 85.71%
src/lib/i18n/pluginLocales.ts 0% 0% 100%
src/lib/i18n/seedUtils.ts 100% 100% 90.47%
src/lib/imageCrop.ts 12.19% 10% 0%
src/lib/iracingParser.ts 91.93% 80% 76.47%
src/lib/kartStorage.ts 100% 75% 100%
src/lib/lapAlignment.ts 100% 80% 76.92%
src/lib/lapCalculation.ts 96.2% 100% 90.57%
src/lib/lapDelta.ts 99.2% 100% 85.07%
src/lib/lapOverlays.ts 100% 100% 86%
src/lib/lapSnapshot.ts 100% 100% 88.46%
src/lib/lapSnapshotStorage.ts 100% 83.33% 100%
src/lib/leaderboardBrowse.ts 100% 92.3% 80.76%
src/lib/leaderboardHandoff.ts 100% 100% 100%
src/lib/leaderboardSession.ts 97.67% 83.33% 67.85%
src/lib/leaderboardTypes.ts 100% 100% 100%
src/lib/logFileType.ts 100% 100% 100%
src/lib/loggers/alfano/alfanoConnection.ts 100% 100% 100%
src/lib/loggers/alfano/ipc.ts 100% 100% 100%
src/lib/loggers/bleDetails.ts 11.11% 11.11% 100%
src/lib/loggers/doveslogger/dovesloggerConnection.ts 56.25% 53.33% 100%
src/lib/loggers/doveslogger/firmwareInfo.ts 100% 100% 100%
src/lib/loggers/doveslogger/ipc.ts 100% 91.66% 66.66%
src/lib/loggers/errors.ts 100% 100% 100%
src/lib/loggers/fileNaming.ts 100% 100% 100%
src/lib/loggers/fledglingConnection.ts 100% 100% 100%
src/lib/loggers/index.ts 100% 100% 100%
src/lib/loggers/mychron/ipc.ts 100% 100% 100%
src/lib/loggers/mychron/mychronConnection.ts 100% 100% 100%
src/lib/loggers/native/ipc.ts 100% 100% 100%
src/lib/loggers/native/owner.ts 100% 100% 100%
src/lib/loggers/progress.ts 94.73% 100% 96.15%
src/lib/loggers/types.ts 100% 100% 100%
src/lib/mapMarker.ts 100% 100% 100%
src/lib/motecParser.ts 89.61% 81.48% 55.71%
src/lib/navBack.ts 100% 100% 71.42%
src/lib/nmeaParser.ts 85.62% 92.85% 71.22%
src/lib/noteStorage.ts 100% 80% 100%
src/lib/overlayCanvasRenderer.ts 0% 0% 0%
src/lib/parseReport.ts 68.18% 85.71% 72.22%
src/lib/parserUtils.ts 100% 100% 98.93%
src/lib/passwordStrength.ts 100% 100% 100%
src/lib/pendingCheckout.ts 58.82% 25% 100%
src/lib/platform.ts 100% 88.88% 89.65%
src/lib/profanity.ts 100% 100% 75%
src/lib/referenceUtils.ts 98.29% 100% 86.66%
src/lib/rssFeed.ts 0% 100% 100%
src/lib/sampleData.ts 100% 100% 100%
src/lib/satelliteImagery.ts 100% 100% 90%
src/lib/setupHistory.ts 94.17% 100% 72.51%
src/lib/setupRevision.ts 100% 100% 94.11%
src/lib/setupRevisionStorage.ts 84.48% 78.26% 36.84%
src/lib/setupStatus.ts 100% 100% 100%
src/lib/setupStorage.ts 81.35% 58.62% 100%
src/lib/shareSession.ts 100% 100% 100%
src/lib/sim/simClient.ts 0% 0% 0%
src/lib/sim/simPlayback.ts 100% 100% 97.22%
src/lib/sim/simSession.ts 100% 100% 100%
src/lib/speedBounds.ts 94.28% 66.66% 87.17%
src/lib/speedEvents.ts 86.56% 100% 76%
src/lib/speedHeatmap.ts 100% 100% 100%
src/lib/sprintCourse.ts 100% 100% 92.3%
src/lib/submittedTracksStorage.ts 0% 0% 0%
src/lib/templateEdit.ts 97.82% 88.88% 86.95%
src/lib/templateStorage.ts 93.54% 69.23% 100%
src/lib/trackStorage.ts 16.4% 28.3% 18.18%
src/lib/trackSubmission.ts 100% 100% 92.64%
src/lib/trackUtils.ts 100% 100% 97.05%
src/lib/ubxParser.ts 99% 100% 89.58%
src/lib/units.ts 100% 100% 100%
src/lib/updateFlow.ts 100% 100% 100%
src/lib/utils.ts 100% 100% 100%
src/lib/vboParser.ts 91.71% 100% 77.83%
src/lib/vehicleHistory.ts 97.29% 100% 80%
src/lib/vehicleStorage.ts 100% 75% 100%
src/lib/versionCheck.ts 19.44% 12.5% 44.73%
src/lib/videoExport.ts 0% 0% 0%
src/lib/videoExportTarget.ts 100% 100% 84.61%
src/lib/videoFileStorage.ts 100% 76% 61.11%
src/lib/videoPlaylist.ts 95.71% 100% 90%
src/lib/videoStorage.ts 100% 76.92% 77.77%
src/lib/videoTimeline.ts 100% 100% 100%
src/lib/wakeLock.ts 100% 80% 100%
src/lib/weatherCacheStorage.ts 100% 100% 100%
src/lib/weatherService.ts 23.8% 35.29% 25.89%
src/lib/xrk/xrkClient.ts 3.57% 0% 0%
src/lib/xrk/xrkConfig.ts 100% 100% 100%
src/lib/xrk/xrkImporter.ts 70% 75% 80%
src/lib/xrk/xrkMapping.ts 98.7% 100% 87.5%
src/lib/xrk/xrkResample.ts 100% 100% 94%
src/lib/xrk/xrkTypes.ts 100% 100% 100%
src/lib/xrk/xrkWorker.ts 0% 0% 0%
src/plugins/cloud-sync/accountDeletion.ts 100% 100% 100%
src/plugins/cloud-sync/accountExport.ts 0% 0% 0%
src/plugins/cloud-sync/accountImport.ts 13.51% 25% 26.08%
src/plugins/cloud-sync/activeUser.ts 100% 100% 100%
src/plugins/cloud-sync/autoSync.ts 0% 0% 0%
src/plugins/cloud-sync/cloudClient.ts 55% 25% 87.5%
src/plugins/cloud-sync/CloudLogsPanel.tsx 0% 0% 0%
src/plugins/cloud-sync/DataPrivacyPanel.tsx 0% 0% 0%
src/plugins/cloud-sync/exportManifest.ts 100% 100% 100%
src/plugins/cloud-sync/FileDeleteToggle.tsx 0% 0% 0%
src/plugins/cloud-sync/fileSync.ts 91.66% 85.71% 100%
src/plugins/cloud-sync/FileSyncToggle.tsx 0% 0% 0%
src/plugins/cloud-sync/index.ts 0% 0% 0%
src/plugins/cloud-sync/LapSnapshotsPanel.tsx 0% 0% 0%
src/plugins/cloud-sync/leaderboardClient.ts 8.92% 10.52% 1.56%
src/plugins/cloud-sync/leaderboardSubmission.ts 100% 100% 94.11%
src/plugins/cloud-sync/LeaderboardSubmitPanel.tsx 0% 0% 0%
src/plugins/cloud-sync/localUsage.ts 100% 100% 50%
src/plugins/cloud-sync/merge.ts 100% 100% 100%
src/plugins/cloud-sync/pendingSync.ts 100% 100% 100%
src/plugins/cloud-sync/postsClient.ts 0% 0% 0%
src/plugins/cloud-sync/profile.ts 61.53% 50% 63.33%
src/plugins/cloud-sync/publicProfile.ts 6.25% 28.57% 0%
src/plugins/cloud-sync/publicShare.ts 100% 100% 100%
src/plugins/cloud-sync/publicVehicleSync.ts 92.85% 100% 78.57%
src/plugins/cloud-sync/sessionShare.ts 92.15% 76.92% 91.66%
src/plugins/cloud-sync/setupRevisionTombstones.ts 100% 100% 83.33%
src/plugins/cloud-sync/ShareFileButton.tsx 0% 0% 0%
src/plugins/cloud-sync/ShareSessionDialog.tsx 0% 0% 0%
src/plugins/cloud-sync/shareState.ts 100% 100% 100%
src/plugins/cloud-sync/shareToken.ts 100% 100% 100%
src/plugins/cloud-sync/snapshotSync.ts 97.22% 87.5% 75%
src/plugins/cloud-sync/snapshotTombstones.ts 100% 100% 100%
src/plugins/cloud-sync/StoragePanel.tsx 0% 0% 0%
src/plugins/cloud-sync/storageTypes.ts 100% 100% 100%
src/plugins/cloud-sync/storeAccessors.ts 100% 100% 90%
src/plugins/cloud-sync/syncEngine.ts 99.05% 91.3% 80%
src/plugins/cloud-sync/syncStores.ts 100% 100% 100%
src/plugins/cloud-sync/trackAutoSubmit.ts 100% 100% 78.57%
src/plugins/fileSources.ts 0% 0% 100%
src/plugins/index.ts 0% 0% 0%
src/plugins/mounts.ts 71.42% 75% 100%
src/plugins/panels.ts 75% 83.33% 100%
src/plugins/PluginMount.tsx 0% 0% 0%
src/plugins/PluginPanelHost.tsx 0% 0% 0%
src/plugins/registry.ts 77.27% 50% 100%
src/plugins/storage.ts 90.32% 70.83% 66.66%
src/plugins/tools/i18n.ts 0% 0% 100%
src/plugins/tools/index.ts 0% 0% 100%
src/plugins/tools/laptimer/lapTimerSession.ts 89.06% 80% 84.37%
src/plugins/tools/laptimer/LapTimerTool.tsx 0% 0% 0%
src/plugins/tools/laptimer/useLapTimer.ts 0% 0% 0%
src/plugins/tools/pill-alignment/CalibrationPanel.tsx 0% 0% 0%
src/plugins/tools/pill-alignment/envelope.ts 100% 100% 90.9%
src/plugins/tools/pill-alignment/EnvelopePlot.tsx 0% 0% 0%
src/plugins/tools/pill-alignment/FindSetupPanel.tsx 0% 0% 0%
src/plugins/tools/pill-alignment/inverse.ts 95.83% 100% 88.52%
src/plugins/tools/pill-alignment/model.ts 100% 100% 92.85%
src/plugins/tools/pill-alignment/OverheadToeView.tsx 0% 0% 100%
src/plugins/tools/pill-alignment/PillAlignmentTool.tsx 0% 0% 0%
src/plugins/tools/pill-alignment/PillDial.tsx 0% 0% 0%
src/plugins/tools/pill-alignment/profiles.ts 100% 100% 84.61%
src/plugins/tools/pill-alignment/toe.ts 100% 100% 100%
src/plugins/tools/seat-position/model.ts 100% 100% 60%
src/plugins/tools/seat-position/SeatDiagram.tsx 0% 0% 0%
src/plugins/tools/seat-position/SeatPositionTool.tsx 0% 0% 0%
src/plugins/tools/shared/NumRow.tsx 0% 0% 0%
src/plugins/tools/toolList.ts 0% 0% 100%
src/plugins/tools/ToolsLandingTile.tsx 0% 0% 0%
src/plugins/tools/ToolsPanel.tsx 0% 0% 0%
src/plugins/types.ts 100% 100% 100%
src/types/racing.ts 100% 100% 100%

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.

2 participants