This file guides AI coding assistants working in this repository. The primary product references are:
runstats-design.mdrunstats-product-backlog.mdAGENT.md
Read these files before implementing a backlog item or changing application architecture.
Implement RunStats as a local-first Python and React application that connects to a Garmin watch, imports running activities and health stats, stores them in SQLite, renders them in a React UI, and provides a grounded chatbot for asking questions about the local data.
The assistant should build incrementally, keep changes well tested, and leave the repository easier to continue than it found it.
- Implement the requested backlog item end to end when feasible.
- Keep changes scoped to the current task.
- Prefer existing project patterns once they exist.
- Add or update tests with every behavior change.
- Treat a comprehensive unit test suite as required validation for implemented logic, not as optional cleanup.
- Do not require a physical Garmin watch, live Bluetooth device, or hosted LLM for unit tests.
- Mock Bluetooth providers, FIT payloads, schedulers, clocks, and LLM providers in tests.
- Keep health data privacy requirements visible in code and UI decisions.
- Update documentation when behavior, commands, or architecture changes.
The intended layout is:
backend/
runstats/
api/
bluetooth/
chat/
db/
importers/
services/
tests/
frontend/
src/
tests/
data/
runstats-design.md
runstats-product-backlog.md
AGENT.md
If implementation discovers a better structure, update the documentation and explain the reason in the implementation summary.
- Identify the relevant backlog item or design section.
- Inspect the current code before editing.
- Plan the smallest useful vertical slice.
- Add or update tests first when the expected behavior is clear.
- Implement the change.
- Run targeted tests for the changed area.
- Run the broader validation suite before final handoff when practical.
- Update docs or backlog status if the implementation changes the plan.
- Provide a concise implementation summary, validation results, and proposed git commit metadata.
- Use FastAPI for HTTP and WebSocket APIs.
- Keep route handlers thin. Put domain behavior in services.
- Use SQLAlchemy 2.x models and sessions for persistence.
- Use Alembic for schema changes.
- Use Pydantic models for request and response contracts.
- Keep database values in canonical metric units.
- Use explicit structured errors with stable error codes.
- Ensure imports and sync writes are transactional.
- Keep provider-specific Bluetooth behavior behind
WatchProvider. - Keep chatbot database access behind approved read-only service methods and tools.
- Use React with TypeScript.
- Use typed API clients.
- Use TanStack Query or the selected data-fetching pattern consistently.
- Build real app screens, not marketing pages.
- Every view should handle loading, empty, success, and error states.
- Watch Settings must handle Bluetooth unavailable, scanning, pairing, connected, syncing, failed, and succeeded states.
- Chat Assistant must show useful unavailable-data states and link answers back to referenced activities, charts, or sync runs when those references exist.
- The chatbot must not execute arbitrary model-generated SQL directly.
- Chat tools must be read-only.
- Tool results sent to an LLM should be the minimum useful summaries, not the entire database.
- Hosted model usage must be explicit and configurable.
- Unit tests must use a fake LLM provider.
- Health-related answers must describe observed data trends and avoid diagnosis or medical advice.
- Store tool traces as lightweight metadata: intent, date range, metrics, row counts, and referenced ids.
Every implemented change must be validated by tests. The expected level depends on the changed surface area.
Unit tests are required for new or changed:
- Services
- Importers
- Normalizers
- Analytics functions
- Chat tools and orchestration
- Bluetooth provider adapters
- Error mapping
- Configuration parsing
- Frontend utility functions and API clients
Unit tests should cover:
- Success paths
- Empty data
- Missing optional fields
- Invalid input
- Duplicate detection
- Permission or provider failures
- Boundary dates and time ranges
Integration tests are required for:
- FastAPI endpoints
- Database migrations
- SQLite persistence behavior
- Import transactions
- Sync lifecycle
- WebSocket progress streams
Use temporary databases for tests. Do not share local developer data across tests.
Frontend tests are required for:
- Route rendering
- Forms and validation
- Tables and filters
- Loading, empty, and error states
- Watch setup interactions
- Chat message submission and answer rendering
Mock backend APIs for component tests unless an end-to-end test is explicitly being written.
Add Playwright or equivalent tests once the app shell is stable.
Important flows:
- Dashboard loads with seeded data.
- Activity filters and details work.
- Watch settings can scan, pair, save settings, and run fake sync.
- Chat Assistant answers a seeded-data question and links to source data.
Before final handoff, run the most complete practical validation.
At minimum:
- Run targeted tests for touched backend or frontend areas.
- Run linting and type checks for touched language surfaces if configured.
- Run migration checks when database schema changes.
- Run frontend build when UI build configuration changes.
If a full suite cannot be run, state exactly what was run and why the remaining validation was not run.
Do not claim validation succeeded unless the command was actually run.
The exact commands may change as tooling is added. Keep this section updated.
Root commands:
npm run install:all
npm run validate
npm run e2eBackend commands:
cd backend
uv sync --extra dev
uv run pytest
uv run ruff check .
uv run mypy runstatsFrontend commands:
cd frontend
npm install
npm test
npm run e2e:install
npm run e2e
npm run lint
npm run typecheck
npm run buildThe root npm run validate command wraps backend tests, backend linting,
backend type checking, frontend tests, frontend linting, frontend type checking,
and the frontend production build. The root npm run e2e command runs the
browser-level cross-phase suite against a seeded local FastAPI server.
After implementing a change, provide proposed git commit metadata in the final response. Do this even if the assistant does not create the commit.
Use this format:
Proposed commit title:
<imperative summary, 72 characters or fewer>
Proposed commit description:
- What changed: <short description of implementation>
- Validation: <commands/tests run and outcomes>
- Notes: <migration, docs, or follow-up context if relevant>
A good title is specific and action-oriented, for example:
Add SQLite models and initial migrationImplement activity summary APIAdd chat assistant persistence endpoints
Do not include vague titles such as Update files or Fix stuff.
When work is complete, the assistant should report:
- What changed
- Tests or validation commands run
- Any validation that could not be run
- Proposed commit title
- Proposed commit description
Keep the summary concise, but include enough validation detail for the next developer to trust the handoff.
If implementation is blocked:
- Explain the blocker clearly.
- State what was already validated or inspected.
- Suggest the smallest next decision needed.
- Do not invent behavior that conflicts with
runstats-design.md.