Repository navigation
Release 2.0.0 - #34
Merged
Merged
Conversation
…quence hardening (ROADMAP 2.6, 3.3, 3.13) (#24) * docs(agents): follow common UI conventions and WCAG 2.2 AA Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * feat(ui): keyboard shortcuts, live tab title, and bounded dependencies (ROADMAP 2.6, 3.3, 3.13) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(ui): drop Start shortcut, swallow keys for disabled buttons, per-screen shortcut help (ROADMAP 3.3) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(ui): harden shortcuts and belt sequences from review (ROADMAP 3.3, 3.13, 3.18) Shortcuts: - Derive tooltips and the ? list in JS from aria-keyshortcuts; hotkey() now emits only that attribute - Track keyboard vs mouse focus via capture-phase keydown/pointerdown instead of :focus-visible, so Space presses a keyboard-focused control but not one focused by a mouse click or script - Restore focus when the ? list closes (WCAG 2.4.3); block keys while any modal is opening; only block for the phone menu while it's visible - Create the help modal lazily so shortcuts survive a Bootstrap CDN failure Belt sequences: - Set belt_transitioning in the start/pause/resume/end routes, guarded by a generation counter so only the newest sequence can clear it; reset it when a new BLE loop starts - Register sequences and speed changes before cancelling their predecessor, so they can't run concurrently or escape a disconnect - _cancel_task: let the caller's own cancellation propagate, and cancel tasks from another event loop on that loop - End Session stops the belt when it cancels an unfinished sequence - Ignore speed changes while a belt sequence is in flight, checked and queued under the session lock - Round, not truncate, km/h to device units (3.8 + 0.6 set 4.3) Pages: - Render buttons disabled while transitioning, re-enabling after 15 s if no stats update arrives; reload on back/forward-cache restore - Single tab-title format, reset by the shutdown overlay, which also stops stats handling (connecting page included) Docs: CHANGELOG, ROADMAP 2.6/3.3/3.13/3.18, new 1.8 (C2 behavior after the physical remote, dropped back-to-back commands, app_speed target). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(ui): cancel pending speed change on pause/end; tidy review nits (ROADMAP 3.3, 3.13) - Pause and End sequences cancel a queued speed change before stop_belt, so a step can't reach a stopped belt; correct the misleading comment - _handle_disconnect: suppress RuntimeError from task.cancel() on a closed loop, so a stale task can't abort reconnect scheduling - _cancel_task: log an error a task raised while being cancelled - Settings hint uses parentheses instead of " -- " - Tab title only reassigned when it changes Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * docs(roadmap): add 1.9 firmware version check and update Opt-in check of the pad's firmware against KingSmith's latest, and an over-the-air update replicating KS Fit, with no firmware bundled. Starts with a spike decompiling KS Fit 6.6.0 to find the version endpoint, image format, and update procedure; the update is built only if that procedure proves safe. Also notes the C2's firmware (6.1.2, software 6.3.0) in 1.8. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test(ble): make pending-speed-change cancel test version-independent On Python 3.10, asyncio.wait_for returns normally when a cancel lands as the lock is handed over, so asserting the step was cancelled failed there (3.12+ raises). Model the actual hazard instead: a step waiting on its predecessor outside the lock while Pause/End takes it. Passes on 3.10 and 3.12; fails on both without the cancel. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * docs(agents): run new or changed tests on every CI Python version Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…ADMAP 1.9) (#25) KS Fit's firmware check needs a KS Fit account session; record the endpoint, image, and OTA findings for any future revisit. Ignore tmp/ so local research artifacts stay untracked. Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
The WalkingPad turns itself off after sitting paused, and the app then hid the session behind the Connecting/Connection Failed screens with no way to resume or end it. Keep the paused screen up while disconnected, with End Session and, once auto-reconnect gives up, Reconnect. Refuse Resume while disconnected instead of queuing commands for a dead link. Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…ent (ROADMAP 4.5) (#27) * docs(roadmap): plan heart rate via BLE HRS, profiles first, speed-based calories (ROADMAP 3.10, 4.5) Co-Authored-By: Claude <noreply@anthropic.com> * feat: per-user profiles with walker picker and history filter (ROADMAP 4.5) History mixed everyone's sessions together. Profiles attribute each session to a walker and store optional height and weight for the upcoming calorie model (ROADMAP 3.10). With no profiles, nothing changes. Storage: - profiles table (id, name unique case-insensitive, height_m, weight_kg, created_at); schema_version 3, upgraded in place - sessions.profile holds the profile id; 'default' (storage.UNASSIGNED) means Unassigned - Profile CRUD, count_unassigned() and assign_unassigned(); delete_profile() moves the profile's sessions to Unassigned in the same transaction instead of deleting them Settings: - Profiles section to add, rename, set height (whole ft/in) and weight (lb), and delete; stored in m and kg - Inline errors take focus so they're visible below the long settings form; the add form keeps what was typed - Creating a profile while Unassigned sessions exist offers to assign them, and offers again on later creations until they're claimed Start: - "Who's walking?" radio group: hidden with 0 profiles, preselected with 1, required with 2+. Uses native required validation instead of a disabled Start, since base.html re-enables Start on every SSE tick and a disabled button can't be focused or explain itself - /start rejects a missing or stale profile_id (?walker_error=1); if profiles can't be read, the session still starts as Unassigned - Active and paused screens show the walker; the Apple Health banner names them History: - Walker column and an All / name / Unassigned filter (?walker=) - Export CSV follows the filter and appends a trailing walker column, so existing spreadsheets keep working - Clear follows the filter and its confirm names the scope; a walker deleted in another tab returns 409 and clears nothing, instead of widening to all history Co-Authored-By: Claude <noreply@anthropic.com> * fix(profiles): scope unassigned claims to completed sessions, keep CSV unchanged without profiles (ROADMAP 4.5) - count_unassigned()/assign_unassigned() only match completed sessions, so an in-progress or crash-interrupted walk isn't counted in the "Assign N sessions" prompt or re-tagged by it, matching how history and Clear already scope to completed rows - Export CSV adds the trailing walker column only once profiles exist, so exports for households without profiles are unchanged - README: finish the Profiles bullet (height/weight are for calorie estimates); CHANGELOG: the claim offer repeats on each new profile while unassigned sessions remain, not only the first; ROADMAP 4.5 matches both Co-Authored-By: Claude <noreply@anthropic.com> * docs(roadmap): plan settings sub-pages and opt-in profiles (ROADMAP 3.20, 3.4) Co-Authored-By: Claude <noreply@anthropic.com> * fix(settings): move Profiles above the settings form so Save Settings ends the page (ROADMAP 4.5) Profiles save per record with their own buttons, so placing the card after Save Settings made Save look like it applied to them. Interim layout until the settings sub-pages (ROADMAP 3.20). Co-Authored-By: Claude <noreply@anthropic.com> * fix(settings): reveal the add-profile form from an Add Profile button (ROADMAP 4.5) An always-visible empty Name/Height/Weight row read as a blank profile. Add Profile now expands the form (focus moves to Name), with Save Profile and Cancel; it stays open after a failed create so the error and typed values remain visible. Co-Authored-By: Claude <noreply@anthropic.com> * fix(ui): use dropdowns for the walker picker and history filter (ROADMAP 4.5) Button rows don't scale past a few names. The Start picker becomes a required "Who's walking?" select (placeholder with 2+ profiles, preselected with 1); the history filter becomes a labelled select with a Show button rather than filtering on change (WCAG 3.2.2). Drop the chip CSS only the radios used. Co-Authored-By: Claude <noreply@anthropic.com> * fix(ui): pick the walker with "Start as <name>" under Start, defaulting to the last walker (ROADMAP 4.5) The labelled dropdown above Start looked bolted onto the console. Chosen from mockups: a quiet "as Sean ⌄" line under Start, a native select styled as an inline link. It defaults to the most recent session's walker (or the only profile), so most starts are one click; with 2+ profiles and no previous walker it reads "choose a walker" and stays required. Co-Authored-By: Claude <noreply@anthropic.com> * feat(ui): tie history to the selected walker, reassign in Edit, theme dropdown lists (ROADMAP 4.5) History now follows the "as <walker>" picker ("Sean's Sessions"): changing it swaps the table in place via GET /history?walker= (no reload, announced to screen readers), replacing the filter dropdown. Edit mode adds a Show scope (walker / All / Unassigned / names) and a per-row Walker dropdown that reassigns completed sessions immediately (POST /session/<id>/walker). Export CSV and Clear follow what's shown. Dropdown lists use the active color theme where customizable selects are supported (appearance: base-select; Chrome/Edge 135+, Safari 27), falling back to native lists, dark in dark mode via color-scheme. Delete and reassign use event delegation so swapped-in rows work. Co-Authored-By: Claude <noreply@anthropic.com> * fix(ui): drop the lingering focus ring after picking a walker with the mouse (ROADMAP 4.5) A select keeps focus after a mouse pick and browsers then match :focus-visible, leaving the ring on. Reuse the pointer/keyboard intent tracker (ROADMAP 3.3) to expose data-intent on <html>, and hide the ring on the walker selects only after pointer input; keyboard focus still shows it. Co-Authored-By: Claude <noreply@anthropic.com> --------- Co-authored-by: Claude <noreply@anthropic.com>
* feat(storage): version and migrate stored data, refuse newer formats (ROADMAP 2.10) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(storage): refuse unusable schema versions cleanly, stamp imported rows (ROADMAP 2.10) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(storage): single unknown-key warning, non-WAL backups, WAL backup test (ROADMAP 2.10) - Move the unknown config.json key warning out of prepare_data() into warn_unknown_settings(), called only from the server's startup. Both run.py and the server ran prepare_data, so the warning printed twice. - Switch pre-upgrade DB backups to journal_mode=DELETE, so opening a backup doesn't leave -wal/-shm files in data/backups/. - Test that a backup includes writes still in the WAL file (a connection held open with autocheckpoint off), which the earlier test couldn't reach because closing the connection checkpointed the WAL. - README: an existing config.json gets its version on the next Settings save, backups are named after the database file, and quit any running copy before starting a newer one (the check only notices one on the same port). - ROADMAP: record why a newer session_state.json is refused even when it says no walk is active. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…until restart (#29) * fix(ble): give the connect its own 10 s timeout - The connect plus service discovery shared the 5 s per-command timeout, so a slow macOS connect timed out mid-discovery - Add _BLE_CONNECT_TIMEOUT_SECONDS = 10 for controller.run(); commands keep 5 s - Tests for a slow connect succeeding and an over-limit connect still timing out Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(ble): disconnect after a failed connect and name the error - A connect that failed partway left the half-open connection open, so the pad stopped advertising and every retry missed it until restart; disconnect before re-raising - Log connect and auto-reconnect failures with the exception type (e.g. TimeoutError()) instead of a blank message - Tests for both, plus a CHANGELOG entry Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* feat(ui): Ledger interface redesign (ROADMAP 3.21) - Replace Bootstrap and the inline styles with static/ledger.css, themes.css and ledger.js - Side rail, one title row per screen, panel layout; tablet breakpoint (3.17) - Themed dialogs replace confirm()/alert() for shut down, delete and clear (3.15) - Belt-speed ladder over the existing speed commands; connection screens show device and last walk - Rename Frost to Holly and Harvest to Pumpkin, migrating saved choices - VT theme follows brand.vt.edu; seasonal fonts and layer-relative ambient effects - Update README, ROADMAP, CHANGELOG and screenshots Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(ui): Safari theme-switch hang and select arrow (ROADMAP 3.21) - Drop position-try-fallbacks from the theme menu; with it, WebKit hangs when a theme's web font loads after the menu opened - Draw the select arrow as one SVG chevron in both select paths; Safari clipped the gradient and rotated-border versions - Add ROADMAP 3.23 (drag the belt ladder to any speed) as a follow-on Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(ui): keep Tide's crabs visible over the save bar and phone nav (ROADMAP 3.21) - Lower the sticky Settings save bar below the ambient-effects layer - End the effects layer at the phone bottom bar so crabs walk above it Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * feat(ui): use the WalkingDad logo as the rail mark (ROADMAP 3.21) - Trace images/logo.png into one currentColor SVG path, so it follows the color theme - Replace the mock's stick-figure-on-a-belt mark Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(ui): rail order, theme contrast and review fixes (ROADMAP 3.21) - Rail: Walk, then Theme, Light/Dark and Shortcuts; Settings above Shut down; theme menu pinned beside the rail - Themes: lighten or darken failing colors in OKLCH (hue kept) so dark buttons, hovers, the belt ladder and field borders meet WCAG AA; VT's dark selected preset gets an orange ring instead - Add tests/test_theme_contrast.py checking every theme in both modes - Phone Save bar clears the bottom nav; heart tooltip no longer clipped; Space pauses from the focused ladder; key hints hidden on touch screens - Remove unused mock CSS and stale comments Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(lint): clear ruff findings that failed CI (ROADMAP 3.21) - Parse the last-walk label with datetime.fromisoformat instead of a naive strptime (DTZ007) - Same for the connecting-screen test's start time (DTZ001) - Use re.DOTALL / re.MULTILINE in the theme contrast test (FURB167) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
- ruff --output-format=github turns each finding into a line annotation - Name the install, lint and test steps; pytest -ra adds a short failure summary - AGENTS.md: run every CI step, ruff included, before handing over cd tmp/ci-branch Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
- Theme menu: presentational group labels and aria-haspopup="menu" on its button - Selected preset stop is aria-current, not aria-pressed - Focus moves to a neighbouring Delete (or Edit) after deleting a history row - Add profile renders open so it works without JavaScript; script folds it on load Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
- Release Unreleased as 2.0.0 with an upgrade note for the new browser minimum - Map the 9 items completed since 1.9.0 to [2.0.0] in ROADMAP - Use bullet metadata (Status, Changelog, Priority, ...) for every ROADMAP item - List the minimum browser versions in README requirements Co-authored-by: Claude <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Merges
developmentintomainfor the 2.0.0 release. Full details are inCHANGELOG.mdunder[2.0.0].Upgrading from 1.x
Added
Spacepauses or resumes, the arrow keys orW/Schange speed, andL/K/Mpick presets.?lists them. They can be turned off in Settings.data/backups/before a format upgrade, and future versions refuse data written by a newer one.Changed
config.jsonkeys log a warning at startup.Fixed
Internal
rufffindings on the PR (ci: annotate ruff findings on the PR and name the steps #31).AGENTS.mdadds rules for UI conventions/WCAG 2.2 AA and for running tests on every CI Python version.Testing
pytest: 561 passed on Python 3.10, 3.12, and 3.13.ruff check: clean.start_app.bat).🤖 Generated with Claude Code