From edf4db025ae89987512f25b9a34d3d0e75cc305f Mon Sep 17 00:00:00 2001 From: Orinks Date: Wed, 27 May 2026 23:34:16 -0400 Subject: [PATCH] docs(agents): remove stale briefcase guidance --- .github/copilot-instructions.md | 150 +++-------- AGENTS.md | 440 ++++++-------------------------- 2 files changed, 117 insertions(+), 473 deletions(-) diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index b9e1a23ad..bde76fdb7 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -1,134 +1,52 @@ # AccessiWeather AI Coding Agent Instructions -## Project Overview -AccessiWeather is a cross-platform, accessible desktop weather application built with BeeWare/Toga (v0.9+) framework and Briefcase for packaging. The app targets Python 3.10+ (3.12 recommended) and prioritizes screen reader accessibility, multi-source weather data, and a simple architecture. +AccessiWeather is a cross-platform accessible desktop weather app built with Python and wxPython. It targets Python 3.11+ and uses Nuitka packaging scripts for desktop artifacts. -## Core Architecture +## Architecture -### Weather Data Sources (Multi-Source Strategy) -- **Primary**: NWS API (weather.gov) for US locations - most accurate, no API key required -- **Fallback**: Open-Meteo for NWS failures or international locations - free, no API key -- **Enrichment**: Visual Crossing for enhanced alert data - requires API key, optional -- **Data Flow**: `WeatherClient` coordinates sources, `WeatherDataCache` caches responses (5-minute default) -- **Alert System**: `AlertManager` + `AlertNotificationSystem` handle notifications with rate limiting and severity filtering +- Entry point: `src/accessiweather/main.py` +- App orchestration: `src/accessiweather/app.py` +- UI: `src/accessiweather/ui/` +- Config: `src/accessiweather/config/` +- API clients: `src/accessiweather/api/` +- Weather orchestration: `src/accessiweather/weather_client.py` +- Alerts: `src/accessiweather/alert_manager.py` and `src/accessiweather/alert_notification_system.py` -### Application Structure -- **Entry Point**: `src/accessiweather/app.py` - Main `AccessiWeatherApp(toga.App)` class -- **Config Management**: `ConfigManager` (JSON-based, uses `toga.App.paths.config`) - - Portable mode supported: checks for `portable.txt` flag to use local config directory - - Settings: `AppSettings` model with validation in `config/settings.py` - - Locations: `LocationOperations` in `config/locations.py` -- **UI Builder**: `ui_builder.py` creates main window and menu system -- **Display Layer**: `WeatherPresenter` formats weather data for screen readers -- **Background Tasks**: Periodic updates via `asyncio.create_task` in `background_tasks.py` +Weather source strategy: -### API Structure -- `api/nws/`: National Weather Service API wrappers (alerts, forecasts, gridpoints) -- `api/openmeteo_wrapper.py`: Open-Meteo integration -- `api/visualcrossing/`: Visual Crossing API (alerts, historical data) -- `api/base_wrapper.py`: Shared HTTP client patterns with retries +- NWS for supported US locations. +- Open-Meteo for international locations and non-alert fallback data. +- Visual Crossing for optional enhanced alert/weather data when configured. -## Toga Framework Specifics +## Development Commands -### Critical Patterns -1. **OptionContainer API**: Use `option_container.content.append(title, widget)` with TWO separate arguments, NOT `.add(title, widget)` or tuple format -2. **Accessibility**: ALL UI elements MUST have `aria_label` and `aria_description` attributes -3. **Testing**: Use Toga dummy backend (`toga_dummy` package) for unit tests - - Set `TOGA_BACKEND=toga_dummy` environment variable - - Fallback to `toga_winforms` on Windows if dummy unavailable -4. **Async Operations**: Toga uses `asyncio` - all long-running operations must be async -5. **Main Thread**: UI updates must happen on main thread, use `app.add_background_task()` for background work - -### Common Gotchas -- OptionContainer: Use `.content.append(title, widget)` with two arguments, NOT tuple format `(title, widget)` -- Toga Selection widget (dropdown) uses `.items` list and `.value` property -- **Error Dialogs**: Use built-in `await app.main_window.error_dialog("Title", "Message")` instead of custom dialog classes -- **Info Dialogs**: Use `await app.main_window.info_dialog("Title", "Message")` for informational messages -- **Question Dialogs**: Use `await app.main_window.question_dialog("Title", "Question")` for yes/no prompts -- Modal dialogs: Create with `toga.Window`, show with `.show()`, close with `.close()` -- Focus management: Call `.focus()` on widgets for accessibility (may fail silently on some platforms) - -## Development Workflow - -### Local Development ```bash -# Run app in development mode (hot reload) -briefcase dev - -# Run tests (uses pytest with Toga dummy backend) -pytest -v -p pytest_asyncio - -# Auto-fix linting issues and format code (run BEFORE committing) -ruff check --fix . -ruff format . - -# Or run both in one line (recommended workflow) +uv run accessiweather +pytest -n auto -v --tb=short ruff check --fix . && ruff format . - -# Type checking (optional, can be noisy) pyright +python installer/build_nuitka.py ``` -### Pre-Commit Hooks -- Auto-formats code with `ruff format` (line length 100) -- Auto-fixes linting issues with `ruff check --fix` -- Runs last-failed unit tests (`pytest --lf --ff -m "unit"`) -- Type checks with pyright (excludes tests/) -- **Important**: Pre-commit will auto-stage formatted files +## wxPython Patterns -### Build & Package -```bash -# Create platform-specific app bundle -briefcase create +- Keep UI work on the wx main thread; use `wx.CallAfter` when crossing thread boundaries. +- Prefer existing `src/accessiweather/ui/` dialogs and helpers over adding new UI patterns. +- Add accessible names/descriptions/status text for new interactive controls. +- Preserve keyboard access and Escape/Cancel behavior in dialogs. +- Tests use the wx stub in `tests/conftest.py` by default. Use `ACCESSIWEATHER_ALLOW_REAL_WX_IN_TESTS=1` only for intentional real-wx checks. -# Build installer (MSI on Windows, DMG on macOS, AppImage on Linux) -briefcase build +## Testing -# Package for distribution -briefcase package -``` +- Unit tests should mock external APIs and OS services. +- Add focused regression tests before fixes. +- Use integration tests only when cassette-backed or explicitly intended to touch live services. +- Run diff coverage for PRs when the CI gate is likely to care. -### Testing Conventions -- **Unit tests**: Fast, isolated tests in `tests/test_*.py` -- **Integration tests**: Test real API calls (marked with `@pytest.mark.integration`) -- **Fixtures**: Reusable test fixtures in `tests/toga_test_helpers.py` - - `DummyConfigManager`: Mock config manager for testing - - `WeatherDataFactory`: Creates mock weather data - # AccessiWeather — AI coding agent quick guide +## Conventions - This file highlights the repository-specific patterns, workflows and commands an AI coding agent should follow to be immediately productive. - - **Architecture & key locations** - - Entry: `src/accessiweather/app.py` (main `AccessiWeatherApp`) - - API wrappers: `api/` (see `api/base_wrapper.py` for shared HTTP client patterns) - - Config: `config/settings.py`, `config/locations.py` and `ConfigManager` (uses `toga.App.paths.config`) - - UI: `ui_builder.py`, `dialogs/` and `WeatherPresenter` for screen-reader formatting - - Background tasks: `background_tasks.py` and `WeatherDataCache` / `WeatherClient` for data flow - - **Must-follow code patterns (examples)** - - OptionContainer: use `option_container.content.append(title, widget)` (two args). Do NOT pass a tuple or use `.add()`. - - Accessibility: every control must set `aria_label` and `aria_description` (see `docs/ACCESSIBILITY.md`). - - Error handling: use `await app.main_window.error_dialog("Title", "Message")` instead of custom dialog classes. - - Async/Toga rules: make long-running code `async`, `await` calls, and use `app.add_background_task()` or `asyncio.create_task()` for background work. Do not use `asyncio.run()` in Toga UI code. - - **Testing & local dev commands** - - Run app (dev): `briefcase dev` - - Tests: `pytest -v -p pytest_asyncio` (use `TOGA_BACKEND=toga_dummy` for unit tests) - - Lint & format: `ruff check --fix . && ruff format .` (pre-commit auto-stages changes) - - Type check (optional): `pyright` - - **When adding features** - - Settings UI: add widget attribute to `SettingsDialog`, update `dialogs/settings_tabs.py`, and wire `apply_settings_to_ui()` / `collect_settings_from_ui()` (see existing pattern in `dialogs/`). - - New API integration: add module under `api/`, implement async client (use `httpx.AsyncClient`), then integrate with `WeatherClient` and `WeatherDataCache`. - - **Important conventions & gotchas** - - Line length: 100 (see `pyproject.toml`/ruff config). - - Use modern type hints: `dict[str, Any]` and `from __future__ import annotations` where applicable. - - Config: always call `config_manager.load_config()` before reading settings; portable mode checks `portable.txt`. - - Alerts: Visual Crossing API requires an API key (gracefully degrade if missing). Rate-limit notifications. - - **Files to inspect for examples** - - `src/accessiweather/app.py`, `api/base_wrapper.py`, `config/settings.py`, `dialogs/settings_handlers.py`, `background_tasks.py`, `tests/toga_test_helpers.py` - - If anything here is unclear or you want more detail on a specific area (tests, packaging, accessibility patterns), tell me which section to expand. -``` +- Use modern type hints and `from __future__ import annotations`. +- Keep line length at 100 and let Ruff format imports/code. +- Update `CHANGELOG.md` for user-visible behavior. +- Use conventional commit messages and PR titles. +- Use `gh api` REST PATCH for PR metadata edits. diff --git a/AGENTS.md b/AGENTS.md index d6c77d521..8e0619673 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,7 +1,7 @@ # AI Agent Guidelines - AccessiWeather -**Role:** You are an expert Python Desktop Application Engineer and Technical Lead specializing in accessible, cross-platform GUI applications. -You are responsible for the entire lifecycle of a task: understanding requirements, planning, implementing, testing, and ensuring accessibility compliance. +**Role:** You are an expert Python Desktop Application Engineer and Technical Lead specializing in accessible, cross-platform wxPython applications. +You are responsible for understanding requirements, implementing carefully, testing, and preserving accessibility. --- @@ -9,449 +9,175 @@ You are responsible for the entire lifecycle of a task: understanding requiremen ```bash # Development -briefcase dev # Run app with hot reload -pytest -v # Run all tests (serial) -pytest -n auto # Run all tests (parallel, ~4x faster) -pytest tests/test_file.py::test_func # Run single test -pytest -k "test_name" -v # Run tests matching pattern +uv run accessiweather # Run the app from source +pytest -v # Run all tests serially +pytest -n auto # Run all tests in parallel +pytest tests/test_file.py::test_func # Run one test +pytest -k "test_name" -v # Run tests matching a pattern pytest --lf --ff -m "unit" # Run last-failed/first-failed unit tests # Linting & Formatting -ruff check --fix . && ruff format . # Lint + format code (line length: 100) -pyright # Type checking (excludes tests/) +ruff check --fix . && ruff format . # Lint and format code +pyright # Type checking; may be scoped for noisy legacy areas # Build & Package -briefcase create # Create platform-specific skeleton -briefcase build # Build app bundle -briefcase package # Generate installers (MSI/DMG/AppImage) -python installer/build.py --dev # Run in development mode - -# Git (Windows) -# Use --no-pager BEFORE the subcommand to prevent hanging on Windows -git --no-pager log --oneline -5 # View recent commits -git --no-pager diff # View changes without pager -git --no-pager show HEAD # Show last commit +python installer/build_nuitka.py # Build packaged app artifacts +python installer/build.py --dev # Run installer build helper in development mode + +# Git on Windows +git --no-pager log --oneline -5 +git --no-pager diff +git --no-pager show HEAD ``` --- ## Project Overview -**AccessiWeather** is a cross-platform desktop weather application built with Python and Toga (BeeWare framework), focusing on screen reader accessibility. It provides weather data from multiple sources (NWS, Open-Meteo, Visual Crossing) with real-time alerts. +AccessiWeather is a cross-platform accessible desktop weather application built with Python and wxPython. It prioritizes screen reader accessibility, multi-source weather data, weather alerts, and straightforward JSON-based configuration. ### Tech Stack | Category | Technology | |----------|------------| -| Language | Python 3.10+ | -| GUI Framework | Toga (BeeWare) | -| HTTP Client | httpx (async) | -| Build Tool | Briefcase | -| Testing | pytest, pytest-asyncio, hypothesis | -| Linting | Ruff (format + lint) | +| Language | Python 3.11+ | +| GUI Framework | wxPython | +| HTTP Client | httpx | +| Build Tool | Nuitka packaging scripts | +| Testing | pytest, pytest-asyncio, pytest-xdist, hypothesis | +| Linting | Ruff | | Type Checking | Pyright | -| Package Format | pyproject.toml (PEP 517) | +| Package Format | pyproject.toml | --- ## Architecture & Codebase Structure -**Main Package**: `src/accessiweather/` - -### Core Modules +**Main Package:** `src/accessiweather/` | Module | Purpose | |--------|---------| -| `app.py` | Main `AccessiWeatherApp(toga.App)` entry point | -| `weather_client.py` | Orchestrates multi-source weather data (NWS, Open-Meteo, Visual Crossing) | +| `app.py` | Main wxPython application orchestration | +| `main.py` | Console/GUI entry point | +| `weather_client.py` | Multi-source weather data orchestration | | `alert_manager.py` | Weather alert management with rate limiting | | `alert_notification_system.py` | Desktop notifications for weather alerts | -| `background_tasks.py` | Async periodic weather updates via `asyncio.create_task()` | -| `cache.py` | 5-minute default TTL cache for API responses | -| `ui_builder.py` | Toga UI construction | - -### Configuration (`config/`) - -| Module | Purpose | -|--------|---------| -| `config_manager.py` | Main configuration orchestration | -| `settings.py` | `AppSettings` dataclass | -| `locations.py` | `LocationOperations` for saved locations | -| `secure_storage.py` | Keyring-based API key storage | -| `source_priority.py` | Weather source priority configuration | - -### API Clients (`api/`) - -| Module | Purpose | -|--------|---------| -| `base_wrapper.py` | Abstract base for API wrappers | -| `openmeteo_wrapper.py` | Open-Meteo API integration | -| `openrouter_models.py` | AI model configuration for explanations | - -### Dialogs (`dialogs/`) - -| Module | Purpose | -|--------|---------| -| `settings_dialog.py` | Settings configuration UI | -| `location_dialog.py` | Location management UI | -| `air_quality_dialog.py` | Air quality details display | -| `aviation_dialog.py` | Aviation weather (METAR/TAF) | -| `weather_history_dialog.py` | Historical weather comparison | +| `background_tasks.py` | Async periodic weather updates | +| `cache.py` | Weather API response caching | +| `ui/` | wxPython windows, dialogs, and UI helpers | +| `config/` | Settings, saved locations, secure storage, and source priority | +| `api/` | NWS, Open-Meteo, Visual Crossing, and related API clients | ### Data Storage -- **Config Location**: `~/.config/accessiweather/accessiweather.json` (or portable directory) -- **No Database**: JSON-based configuration only -- **API Keys**: Stored securely via `keyring` +- Config is JSON-based, stored in the user config directory or a portable directory. +- API keys are stored through keyring-backed secure storage. +- There is no database. --- ## Code Style & Conventions -### Formatting Rules - -- **Tool**: Ruff (line length 100, double quotes, auto-import sorting) -- **Pre-commit**: Auto-formats before commit -- **Type Hints**: Modern syntax (`dict[str, Any]` not `Dict`) -- **Forward Refs**: Use `from __future__ import annotations` -- **File Size**: Code files must not exceed 1000 lines. Split large modules before adding more code. - -### Import Organization - -```python -from __future__ import annotations - -import asyncio # stdlib -from typing import TYPE_CHECKING - -import toga # third-party -import httpx - -from .config import ConfigManager # local imports -from .weather_client import WeatherClient - -if TYPE_CHECKING: # type-only imports - from .alert_manager import AlertManager -``` +- Use Ruff formatting: 100-character line length, double quotes, sorted imports. +- Prefer modern type hints: `dict[str, Any]`, `Location | None`, and `from __future__ import annotations`. +- Keep files under 1000 lines where practical; split large modules before growing them further. +- Preserve unrelated user or agent changes in the working tree. +- Add focused comments only when they explain non-obvious behavior. ### Async Patterns ```python -# DO: Use await for async functions +# DO: await async functions data = await weather_client.fetch_weather() -# DO: Use asyncio.create_task() for fire-and-forget +# DO: schedule background work through the app's existing scheduler or asyncio task helpers asyncio.create_task(background_refresh()) -# DON'T: Never use asyncio.run() in Toga (conflicts with event loop) +# DON'T: call asyncio.run() from GUI code ``` -### Toga-Specific Patterns - -```python -# OptionContainer: Two arguments, NOT tuple -container.content.append("Tab Title", widget) # Correct -container.content.append(("Tab Title", widget)) # WRONG - -# ALL UI elements MUST have accessibility attributes -button = toga.Button( - "Refresh", - on_press=self.refresh, - aria_label="Refresh weather data", - aria_description="Click to fetch latest weather information" -) - -# Modal dialogs -dialog = toga.Window(title="Settings") -dialog.show() # Show -dialog.close() # Close - -# Testing with dummy backend -# Set TOGA_BACKEND=toga_dummy in tests -``` +### wxPython Patterns -**Accessibility Note:** Toga doesn't support semantic label-pairing (see beeware/toga#2233). Screen readers announce adjacent `Label` text when users tab to inputs/selects. Make labels descriptive: `"Search for Location (city/zipcode):"` instead of just `"Search for Location:"`. This works for `TextInput`, `Selection`, and other input widgets. - -### Naming Conventions - -| Type | Convention | Example | -|------|------------|---------| -| Functions/Variables | snake_case | `fetch_weather_data` | -| Classes | PascalCase | `WeatherClient` | -| Constants | UPPER_CASE | `DEFAULT_TIMEOUT` | -| Private | Leading underscore | `_internal_cache` | - -### Error Handling - -```python -# Defensive attribute access -value = getattr(obj, 'attr', default_value) - -# Async operations with try-except -try: - data = await fetch_data() -except httpx.TimeoutException: - logger.warning("Request timed out") - return cached_data -``` +- Keep UI work on the wx main thread; use `wx.CallAfter` when crossing thread boundaries. +- Prefer existing dialog/window helpers and local UI conventions over introducing new frameworks. +- All new interactive controls need accessible labels or names, useful descriptions where supported, keyboard access, and sensible focus behavior. +- Tests normally use the in-repo wx stub from `tests/conftest.py`; set `ACCESSIWEATHER_ALLOW_REAL_WX_IN_TESTS=1` only when a real wxPython smoke test is required. --- ## Testing Guidelines -### Test Organization - -- **Unit tests**: `tests/test_*.py` (mocked dependencies) -- **Integration tests**: `tests/integration/` (real API calls, VCR cassettes) -- **Property tests**: Use Hypothesis for edge cases - -### Running Tests +- Unit tests live under `tests/test_*.py` and should mock external services. +- GUI-focused tests may use the wx stub or live wx under xvfb/Windows only when needed. +- Integration tests live under `tests/integration/` and should avoid live API dependence unless explicitly intended. +- Use Hypothesis for broad input-space edge cases. ```bash -# All tests (parallel) pytest -n auto -v --tb=short - -# Exclude integration tests pytest tests/ -m "not integration" -n auto - -# Single test with output pytest tests/test_weather_client.py::test_fetch -v -s - -# Property tests with thorough profile pytest --hypothesis-profile=thorough ``` -### Test Fixtures - -```python -# conftest.py sets up toga_dummy backend automatically -# Use mock_simple_weather_apis fixture for API mocking - -def test_weather_fetch(mock_simple_weather_apis): - # APIs are mocked, safe to test - pass -``` - -### Hypothesis Profiles - -| Profile | Examples | Use Case | -|---------|----------|----------| -| `ci` | 25 | Fast CI runs | -| `dev` | 50 | Development | -| `thorough` | 200 | Release validation | - --- -## CI/CD Configuration - -### Workflows +## CI/CD -| Workflow | Trigger | Purpose | -|----------|---------|---------| -| `ci.yml` | Push to main/dev, PRs | Linting, tests on Ubuntu/Windows/macOS | -| `briefcase-build.yml` | After CI passes on dev | Build MSI/DMG installers | -| `briefcase-release.yml` | Tags (v*.*.*) | Create GitHub releases | -| `integration-tests.yml` | Nightly | Record VCR cassettes | -| `update-pages.yml` | After builds | Update GitHub Pages downloads | +| Workflow | Purpose | +|----------|---------| +| `ci.yml` | Linting, tests, changelog check, coverage gate | +| `build.yml` | Nuitka desktop build artifacts | +| `integration-tests.yml` | Scheduled integration cassette checks | +| `update-pages.yml` | GitHub Pages/download updates | -### CI Environment Variables +Important CI environment defaults: ```yaml -FORCE_COLOR: "0" # Prevent rich encoding crashes on Windows -PYTHONUTF8: "1" # Force UTF-8 encoding -ACCESSIWEATHER_TEST_MODE: "1" # Enable test mode -HYPOTHESIS_PROFILE: ci # Fast property tests -TOGA_BACKEND: toga_dummy # Headless UI testing +FORCE_COLOR: "0" +PYTHONUTF8: "1" +ACCESSIWEATHER_TEST_MODE: "1" +HYPOTHESIS_PROFILE: ci ``` -### Build Matrix - -| Platform | Output | Notes | -|----------|--------|-------| -| Windows | `.msi` installer, `.zip` portable | Includes pythonnet for WinForms | -| macOS | `.dmg` installer | Universal build (Intel + ARM) | - -### Audio Support - -| Platform | Primary | Fallback | -|----------|---------|----------| -| Windows | `winsound` (stdlib) | `playsound3` | -| macOS/Linux | `playsound3` | - | - --- ## Git Workflow -### Branch Strategy - -| Branch | Purpose | CI/CD | -|--------|---------|-------| -| `main` | Stable releases only | Tagged releases | -| `dev` | Active development | Nightly builds, GitHub Pages | -| `feature/*` | Feature work | PRs to dev | -| `hotfix/*` | Critical fixes | Merge to both main and dev | - -### Commit Message Format - -``` -type(scope): description - -[optional body] - -Types: feat, fix, docs, style, refactor, test, chore -``` - -**Examples:** -``` -feat(alerts): add rate limiting for weather notifications -fix(ui): resolve screen reader focus issue in settings dialog -chore(deps): update httpx to 0.28.1 -``` - -### Branch Naming - -``` -feature/- # feature/123-add-radar-view -fix/- # fix/456-alert-crash -hotfix/ # hotfix/critical-api-timeout -``` - -### Merge Strategy - -1. **Feature branches**: Short-lived, PR to `dev` -2. **Releases**: Merge `dev` to `main`, tag with version -3. **Hotfixes**: Branch from `main`, merge to both `main` and `dev` - -### Creating Releases - -```bash -# 1. Ensure dev is ready -git checkout dev && git push origin dev - -# 2. Merge to main and tag -git checkout main -git merge dev --no-ff -m "Release v1.0.0" -git tag v1.0.0 -git push origin main --tags -``` +- Use conventional commits and conventional PR titles. +- Branch from `dev` for normal feature/fix work. +- PRs should normally target `dev`. +- Use `gh api` REST `PATCH` calls for PR metadata updates instead of `gh pr edit`. +- Use `git --no-pager` for Git inspection commands on Windows. --- ## Security Guidelines -### Environment Variables - -- **Never commit** `.env` files (use `.env.example` as template) -- **API keys** stored via `keyring` (system keychain) -- **Test mode** uses mock data, never real credentials - -### API Key Storage - -```python -# Secure storage via keyring -from .config.secure_storage import SecureStorage - -storage = SecureStorage() -storage.set_api_key("visual_crossing", "your-api-key") -key = storage.get_api_key("visual_crossing") -``` - -### Input Validation - -- Validate coordinates (latitude: -90 to 90, longitude: -180 to 180) -- Sanitize location names before display -- Use `httpx` with timeout limits (prevent hangs) - -### Sensitive Data Handling - -```python -# DON'T log API keys -logger.info(f"Using key: {api_key}") # WRONG - -# DO mask sensitive data -logger.info(f"Using key: {api_key[:4]}...") # OK -``` +- Never commit `.env` files or API keys. +- Store API keys via `SecureStorage`. +- Validate coordinates: latitude `-90..90`, longitude `-180..180`. +- Sanitize user-provided strings before logging. +- Keep HTTP timeouts on external requests. --- ## Accessibility Requirements -**All UI must be screen reader compatible:** - -1. **Every interactive element** needs `aria_label` and `aria_description` -2. **Keyboard navigation** must work for all features -3. **Focus management** - dialogs should trap focus appropriately -4. **Status announcements** - use live regions for updates - -```python -# Example accessible button -toga.Button( - "Check Weather", - on_press=self.check_weather, - aria_label="Check weather", - aria_description="Fetches current weather for your selected location" -) - -# Example accessible table -toga.Table( - headings=["Alert Type", "Severity", "Description"], - aria_label="Weather alerts table", - aria_description="List of active weather alerts for your area" -) -``` +- Every interactive UI element must be reachable by keyboard. +- Controls need clear accessible names and useful descriptions/status text. +- Dialogs should set initial focus intentionally and preserve normal keyboard escape/cancel behavior. +- Dynamic updates should be announced or reflected in status text when useful to screen reader users. --- ## Changelog Maintenance -Keep `CHANGELOG.md` updated with user-facing changes: - -### When to Add - -- User-visible features, fixes, or changes -- UI, behavior, performance, appearance changes - -### What to Skip +Update `CHANGELOG.md` under `[Unreleased]` for user-visible features, fixes, UI behavior, performance, or packaging changes. -- Internal refactoring, CI/CD improvements -- Test-only changes, documentation updates -- Developer-facing changes - -### Writing Style - -Write like a human, not a chatbot: +Write entries like a human: ```markdown -# DON'T -- Performance improvements have been implemented via cache-first design - -# DO -- Performance boost: Now serves cached results instantly while refreshing - in the background - 80%+ fewer API calls +- Detected current locations outside the US now get an editable place name when reverse geocoding can identify the coordinates. ``` -**Avoid**: Passive voice, hedging language, generic terms ("enhanced", "optimized") -**Use**: Contractions, direct address ("You can now..."), specific benefits - ---- - -## Common Gotchas - -1. **Windows Git**: Use `--no-pager` to prevent terminal hangs -2. **Toga OptionContainer**: Use two args, not tuple -3. **asyncio.run()**: Never use in Toga (use `create_task`) -4. **Pre-commit hooks**: Format before committing -5. **TOGA_BACKEND**: Set to `toga_dummy` for headless tests -6. **Encoding on Windows CI**: Set `FORCE_COLOR=0` to prevent crashes - ---- - -## Documentation References - -| Document | Purpose | -|----------|---------| -| `CONTRIBUTING.md` | Contribution guidelines | -| `docs/git-workflow.md` | Detailed git workflow | -| `docs/ACCESSIBILITY.md` | Accessibility standards | -| `docs/user_manual.md` | End-user documentation | -| `.github/workflows/README.md` | CI/CD workflow details | +Skip changelog entries for internal-only refactors, test-only work, and CI plumbing unless users are affected.