Files
geniusrun/backend/geniusrun.db-wal

257 lines
109 KiB
Plaintext
Raw Normal View History

7<06>-<2D><00><><EFBFBD><EFBFBD><EFBFBD>C)<29><><EFBFBD><EFBFBD><EFBFBD><04><00><><EFBFBD><EFBFBD><EFBFBD>C)<29>M9!<21><><EFBFBD><EFBFBD>SQLite format 3@ .<2E><><0F><0F><0F>h<01><01>9M'indexsqlite_autoindex_workout_kinds_1workout_kinds<08>Z<01> tableprofileprofileCREATE TABLE profile (
id INTEGER PRIMARY KEY AUTOINCREMENT,
user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
name TEXT NOT NULL DEFAULT 'Default',
garmin_email TEXT NOT NULL DEFAULT '',
garmin_password TEXT NOT NULL DEFAULT '',
-- Set once, the first time this user successfully authenticates with
-- Garmin (handleAuthLogin/handleAuthMFA). Null means never connected --
-- the login gate uses this (not the in-memory auth status, which
-- resets on restart) to decide whether a returning user must
-- reconnect before entering the app.
garmin_connected_at TEXT,
rolling_window_days INTEGER NOT NULL DEFAULT 90,
-- BackfillHorizonDays bounds how far back "Sync now" reaches when
-- walking backward from today; read fresh on every sync (not cached at
-- server startup), so changing it here takes effect on the next click.
backfill_horizon_days INTEGER NOT NULL DEFAULT 90,
max_heart_rate REAL,
resting_heart_rate REAL,
hr_zone1_min_pct REAL NOT NULL DEFAULT 50,
hr_zone1_max_pct REAL NOT NULL DEFAULT 60,
hr_zone2_min_pct REAL NOT NULL DEFAULT 60,
hr_zone2_max_pct REAL NOT NULL DEFAULT 70,
hr_zone3_min_pct REAL NOT NULL DEFAULT 70,
hr_zone3_max_pct REAL NOT NULL DEFAULT 80,
hr_zone4_min_pct REAL NOT NULL DEFAULT 80,
hr_zone4_max_pct REAL NOT NULL DEFAULT 90,
hr_zone5_min_pct REAL NOT NULL DEFAULT 90,
hr_zone5_max_pct REAL NOT NULL DEFAULT 100,
-- Applies uniformly to every fixed-duration workout type's phase
-- detection (Easy, Long, Tempo, Threshold 30'/60', MAS Test). Interval
-- workouts detect phases from lap data directly and don't use these.
warmup_minutes REAL NOT NULL DEFAULT 10,
cooldown_minutes REAL NOT NULL DEFAULT 5,
-- Review Queue pace-chart artifact filter: a stretch of samples slower
-- than min_representative_pace_sec_per_km is dropped unless it persists
-- for at least min_representative_time_seconds, in which case it's a
-- real stop/walk break rather than GPS/motion noise at recording start.
min_representative_pace_sec_per_km REAL NOT NULL DEFAULT 720,
min_representative_time_seconds REAL NOT NULL DEFAULT 3,
-- Chart colors: pace_color/heart_rate_color are each chart's "main
-- line" color; warmup/effort/recovery/cooldown_color are the "effort
-- kind" colors the frontend derives fills from (see
-- ExpectedVsActualChart).
pace_color TEXT NOT NULL DEFAULT '#3b82f6',
heart_rate_color TEXT NOT NULL DEFAULT '#ef4444',
warmup_color TEXT NOT NULL DEFAULT '#c2410c',
effort_color TEXT NOT NULL DEFAULT '#7c3aed',
recovery_color TEXT NOT NULL DEFAULT '#15803d',
cooldown_color TEXT NOT NULL DEFAULT '#fb923c',
main_line_tint_pct REAL NOT NULL DEFAULT 20,
background_darken_pct REAL NOT NULL DEFAULT 35,
target_brighten_pct REAL NOT NULL DEFAULT 20,
created_at TEXT NOT NULL DEFAULT (datetime('now')),
updated_at TEXT NOT NULL DEFAULT (datetime('now')),
UNIQUE(user_id)
)-Aindexsqlite_autoindex_profile_1profileP++Ytablesqlite_sequencesqlite_sequenceCREATE TABLE sqlite_sequence(name,seq)<29>a<01>!tableusersusersCREATE TABLE users (
id INTEGER PRIMARY KEY AUTOINCREMENT,
oidc_sub TEXT NOT NULL UNIQUE,
display_name TEXT NOT NULL,
created_at TEXT NOT NULL DEFAULT (datetime('now'))
))=indexsqlite_autoindex_users_1user
<00><><EFBFBD><EFBFBD><EFBFBD>C)<0E><>O<EFBFBD>5C<35> 

<EFBFBD>!3<><33>B<EFBFBD> 


id INTEGER PRIMARY KEY AUTOINCREMENT,
user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
name TEXT NOT NULL DEFAULT 'Default',
garmin_email TEXT NOT NULL DEFAULT '',
garmin_password TEXT NOT NULL DEFAULT '',
-- Set once, the first time this user successfully authenticates with
-- Garmin (handleAuthLogin/handleAuthMFA). Null means never connected --
-- the login gate uses this (not the in-memory auth status, which
-- resets on restart) to decide whether a returning user must
-- reconnect before entering the app.
garmin_connected_at TEXT,
rolling_window_days INTEGER NOT NULL DEFAULT 90,
-- BackfillHorizonDays bounds how far back "Sync now" reaches when
-- walking backward from today; read fresh on every sync (not cached at
-- server startup), so changing it here takes effect on the next click.
backfill_horizon_days INTEGER NOT NULL DEFAULT 90,
max_heart_rate REAL,
resting_heart_rate REAL,
hr_zone1_min_pct REAL NOT NULL DEFAULT 50,
hr_zone1_max_pct REAL NOT NULL DEFAULT 60,
hr_zone2_min_pct REAL NOT NULL DEFAULT 60,
hr_zone2_max_pct REAL NOT NULL DEFAULT 70,
hr_zone3_min_pct REAL NOT NULL DEFAULT 70,
hr_zone3_max_pct REAL NOT NULL DEFAULT 80,
hr_zone4_min_pct REAL NOT NULL DEFAULT 80,
hr_zone4_max_pct REAL NOT NULL DEFAULT 90,
hr_zone5_min_pct REAL NOT NULL DEFAULT 90,
hr_zone5_max_pct REAL NOT NULL DEFAULT 100,
-- Applies uniformly to every fixed-duration workout type's phase
-- detection (Easy, Long, Tempo, Threshold 30'/60', MAS Test). Interval
-- workouts detect phases from lap data directly and don't use these.
warmup_minutes REAL NOT NULL DEFAULT 10,
cooldown_minutes REAL NOT NULL DEFAULT 5,
-- Review Queue pace-chart artifact filter: a stretch of samples slower
-- than min_representative_pace_sec_per_km is dropped unless it persists
-- for at least min_representative_time_seconds, in which case it's a
-- real stop/walk break rather than GPS/motion noise at recording start.
min_representative_pace_sec_per_km REAL NOT NULL DEFAULT 720,
min_representative_time_seconds REAL NOT NULL DEFAULT 3,
-- Chart colors: pace_color/heart_rate_color are each chart's "main
-- line" color; warmup/effort/recovery/cooldown_color are the "effort
-- kind" colors the frontend derives fills from (see
-- ExpectedVsActualChart).
pace_color TEXT NOT NULL DEFAULT '#3b82f6',
heart_rate_color TEXT NOT NULL DEFAULT '#ef4444',
warmup_color TEXT NOT NULL DEFAULT '#c2410c',
effort_color TEXT NOT NULL DEFAULT '#7c3aed',
recovery_color TEXT NOT NULL DEFAULT '#15803d',
cooldown_color TEXT NOT NULL DEFAULT '#fb923c',
main_line_tint_pct REAL NOT NULL DEFAULT 20,
background_darken_pct REAL NOT NULL DEFAULT 35,
target_brighten_pct REAL NOT NULL DEFAULT 20,
created_at TEXT NOT NULL DEFAULT (datetime('now')),
updated_at TEXT NOT NULL DEFAULT (datetime('now')),
UNIQUE(user_id)
)<0F>/Aindexsqlite_autoindex_profile_1profileP++Ytablesqlite_sequencesqlite_sequenceCREATE TABLE sqlite_sequence(name,seq)<29>a<01>!tableusersusersCREATE TABLE users (
id INTEGER PRIMARY KEY AUTOINCREMENT,
oidc_sub TEXT NOT NULL UNIQUE,
display_name TEXT NOT NULL,
created_at TEXT NOT NULL DEFAULT (datetime('now'))
))=indexsqlite_autoindex_users_1users
<00><><EFBFBD><EFBFBD><EFBFBD>C)z<><7A><EFBFBD>\<5C>S <0B>U<0F> <0A> \ 2U <0B><02><02><02>' ;indexsqlite_autoindex_laps_1lapst ?!<01>indexidx_activities_start_timeactivitiesCREATE INDEX idx_activities_start_time ON activities(start_time_utc)<29> !!<01>tableactivitiesactivities CREATE TABLE activities (
id INTEGER PRIMARY KEY AUTOINCREMENT,
user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
garmin_activity_id INTEGER NOT NULL,
-- Derived at sync time from Garmin's own eventType.typeKey=="race" --
-- a hard fact, not a rule the user tunes (see internal/classify's
-- is_race metric and handleReclassifyAll's Race special-case).
event_type_key TEXT NOT NULL DEFAULT '',
-- Set when the activity was recorded from a structured Garmin workout;
-- used to resolve each lap's expected pace/HR band (see
-- internal/sync/mapping.go's alignWorkoutTargets).
workout_id INTEGER,
start_time_utc TEXT NOT NULL,
duration_seconds REAL NOT NULL,
distance_meters REAL NOT NULL,
avg_hr REAL,
max_hr REAL,
avg_speed_mps REAL,
elevation_gain_m REAL,
aerobic_training_effect REAL,
anaerobic_training_effect REAL,
vo2max_value REAL,
raw_json TEXT NOT NULL,
details_fetched_at TEXT,
details_raw_json TEXT,
splits_fetched_at TEXT,
-- Genuine raw get_workout_by_id() response, the source used to compute
-- alignWorkoutTargets. Null when the activity has no workout_id.
workout_raw_json TEXT,
-- Set when get_workout_by_id returned a definitive HTTP 404 (the
-- workout was deleted on Garmin's side after being linked to this
-- activity) -- distinct from workout_raw_json staying null for "not yet
-- fetched": this activity is excluded from ActivitiesMissingWorkout so
-- it stops being retried forever (see
-- docs/superpowers/specs/2026-07-27-workout-not-found-design.md).
-- workout_raw_json itself is never fabricated; it just stays null.
workout_not_found_at TEXT,
created_at TEXT NOT NULL DEFAULT (datetime('now')),
updated_at TEXT NOT NULL DEFAULT (datetime('now')),
UNIQUE(user_id, garmin_activity_id)
)=G!indexsqlite_autoindex_activities_1activities <00>'11<01>ytableworkout_type_pacesworkout_type_paces CREATE TABLE workout_type_paces (
workout_kind_id INTEGER PRIMARY KEY REFERENCES workout_kinds(id) ON DELETE CASCADE,
pace_min_sec_per_km REAL,
pace_max_sec_per_km REAL,
hr_min_pct_hrr REAL,
hr_max_pct_hrr REAL
)9M'indexsqlite_autoindex_workout_kinds_1workout_kinds<08>7''<01>-tableworkout_kindsworkout_kindsCREATE TABLE workout_kinds (
id INTEGER PRIMARY KEY AUTOINCREMENT,
user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
name TEXT NOT NULL,
description TEXT NOT NULL DEFAULT '',
color TEXT NOT NULL DEFAULT '',
rule_json TEXT NOT NULL,
priority INTEGER NOT NULL DEFAULT 0,
is_active INTEGER NOT NULL DEFAULT 1,
created_at TEXT NOT NULL DEFAULT (datetime('now')),
updated_at TEXT NOT NULL DEFAULT (datetime('now')),
UNIQUE(user_id, name)
)-Aindexsqlite_autoindex_profile_1profile <00><><EFBFBD><EFBFBD><EFBFBD>C)%<25><><EFBFBD><06>ޮ 



W<EFBFBD><EFBFBD>c<> ,<00><0F>U  <0B>
j <09>g<06>a4<03><04><01><00><01><00>&<01>'tableconfigconfigCREATE TABLE config (
key TEXT PRIMARY KEY,
value TEXT NOT NULL,
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
)+?indexsqlite_autoindex_config_1config<1B><01>Qtablesync_runssync_runsCREATE TABLE sync_runs (
id INTEGER PRIMARY KEY AUTOINCREMENT,
user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
kind TEXT NOT NULL CHECK(kind IN ('backfill','incremental','full')),
started_at TEXT NOT NULL,
finished_at TEXT,
activities_fetched INTEGER NOT NULL DEFAULT 0,
status TEXT NOT NULL CHECK(status IN ('running','success','error')),
error_message TEXT
)<29>2!!<01>/tablesync_statesync_stateCREATE TABLE sync_state (
id INTEGER PRIMARY KEY AUTOINCREMENT,
user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
earliest_synced_date TEXT,
backfill_complete INTEGER NOT NULL DEFAULT 0,
UNIQUE(user_id)
)3G!indexsqlite_autoindex_sync_state_1sync_state<00>*;;<08>oviewcurrent_kind_assignmentcurrent_kind_assignmentCREATE VIEW current_kind_assignment AS
SELECT a.* FROM kind_assignments a
JOIN (
SELECT activity_id, MAX(id) AS max_id
FROM kind_assignments GROUP BY activity_id
) latest ON a.activity_id = latest.activity_id AND a.id = latest.max_id|C-<01>indexidx_kind_assignments_statuskind_assignmentsCREATE INDEX idx_kind_assignments_status ON kind_assignments(status)<29>G-<01>#indexidx_kind_assignments_activitykind_assignmentsCREATE INDEX idx_kind_assignments_activity ON kind_assignments(activity_id)<29>g--<01>tablekind_assignmentskind_assignmentsCREATE TABLE kind_assignments (
id INTEGER PRIMARY KEY AUTOINCREMENT,
activity_id INTEGER NOT NULL REFERENCES activities(id) ON DELETE CASCADE,
workout_kind_id INTEGER REFERENCES workout_kinds(id),
assignment_source TEXT NOT NULL CHECK(assignment_source IN ('rule_engine','manual')),
status TEXT NOT NULL CHECK(status IN ('assigned','needs_review')),
confidence REAL,
candidate_kinds_json TEXT NOT NULL DEFAULT '[]',
created_at TEXT NOT NULL DEFAULT (datetime('now'))
)<29>G-<01>Eindexidx_activity_samples_activityactivity_samplesCREATE INDEX idx_activity_samples_activity ON activity_samples(activity_id, elapsed_seconds)<29>--<01>Atableactivity_samplesactivity_samplesCREATE TABLE activity_samples (
id INTEGER PRIMARY KEY AUTOINCREMENT,
activity_id INTEGER NOT NULL REFERENCES activities(id) ON DELETE CASCADE,
elapsed_seconds REAL NOT NULL,
timestamp_ms INTEGER NOT NULL,
heart_rate REAL,
speed_mps REAL,
distance_m REAL,
elevation_m REAL
)' ;indexsqlite_autoindex_laps_1laps<10>5 <01>MtablelapslapsCREATE TABLE laps (
id INTEGER PRIMARY KEY AUTOINCREMENT,
activity_id INTEGER NOT NULL REFERENCES activities(id) ON DELETE CASCADE,
lap_index INTEGER NOT NULL,
avg_speed_mps REAL,
intensity_type TEXT NOT NULL DEFAULT '',
hr_drift_bpm_per_min REAL,
hr_recovery_bpm_per_min REAL,
-- Expected band for this lap, resolved from the activity's structured
-- Garmin workout when its steps line up 1:1 with the recorded laps.
-- Null when there's no structured workout or the counts don't match.
target_pace_low_mps REAL,
target_pace_high_mps REAL,
target_hr_low_bpm REAL,
target_hr_high_bpm REAL,
raw_json TEXT NOT NULL,
UNIQUE(activity_id, lap_index)
)t ?!<01>indexidx_activities_start_timeactivitiesCREATE INDEX idx_activities_start_time ON activities(start_time_utc)3
G!indexsqlite_autoindex_activities_1activities <00><><EFBFBD><EFBFBD><EFBFBD>C)<29>;a <0B><>-d