|
| 1 | +# PySquared Copilot Instructions |
| 2 | + |
| 3 | +## Repository Overview |
| 4 | + |
| 5 | +**PySquared** is a CircuitPython-based CubeSat flight software library with flight heritage. It provides robust, modular components for spacecraft control, telemetry, configuration, and hardware management designed for microcontroller resource constraints. |
| 6 | + |
| 7 | +### Key Characteristics |
| 8 | +- **Size**: ~142 Python files, ~1,600 lines of code |
| 9 | +- **Languages**: Python (CircuitPython 3.4 subset + type hints) |
| 10 | +- **Primary Framework**: CircuitPython for embedded systems |
| 11 | +- **Test Framework**: pytest with coverage, pyright for type checking |
| 12 | +- **Build System**: Makefile + uv (Python package manager) |
| 13 | +- **Documentation**: MkDocs with Material theme |
| 14 | +- **License**: MIT |
| 15 | + |
| 16 | +### Dual Workspace Architecture |
| 17 | +This repository uses a **unique dual workspace structure** to support both CircuitPython (microcontroller) and CPython (testing/tools): |
| 18 | + |
| 19 | +1. **`circuitpython-workspaces/`**: Code that runs on CircuitPython microcontrollers |
| 20 | + - `flight-software/`: Main PySquared library (`pysquared` package) |
| 21 | + - `ground-station/`: Ground station software |
| 22 | + - Uses CircuitPython typeshed stubs for accurate type checking |
| 23 | + |
| 24 | +2. **`cpython-workspaces/`**: Code that runs on standard Python |
| 25 | + - `flight-software-unit-tests/`: pytest test suite |
| 26 | + - `flight-software-mocks/`: Mock hardware for testing |
| 27 | + - Uses standard Python type hints |
| 28 | + |
| 29 | +**CRITICAL**: Always respect workspace boundaries. CircuitPython code cannot use CPython-only libraries (e.g., `pathlib`, full `typing` module) and vice versa. |
| 30 | + |
| 31 | +## Build & Validation Commands |
| 32 | + |
| 33 | +### Initial Setup (ALWAYS run first) |
| 34 | +```bash |
| 35 | +make |
| 36 | +``` |
| 37 | +This command: |
| 38 | +- Downloads and installs `uv` (v0.8.14) to `tools/uv-0.8.14/` |
| 39 | +- Creates `.venv/` virtual environment |
| 40 | +- Installs all dependencies from `pyproject.toml` |
| 41 | +- Installs CircuitPython typeshed stubs to `circuitpython-workspaces/typeshed/` |
| 42 | +- Installs pre-commit hooks |
| 43 | + |
| 44 | +**Expected time**: 30-60 seconds (first run) |
| 45 | + |
| 46 | +### Linting & Formatting |
| 47 | +```bash |
| 48 | +make fmt |
| 49 | +``` |
| 50 | +- Runs `pre-commit run --all-files` |
| 51 | +- Uses ruff for linting/formatting (follows Black style + isort) |
| 52 | +- Includes custom checks: prevents `# type: ignore`, checks spelling, validates JSON/YAML |
| 53 | +- **ALWAYS run before committing code** |
| 54 | +- Auto-fixes most issues; manual fixes required for some errors |
| 55 | + |
| 56 | +**Expected time**: 10-20 seconds |
| 57 | + |
| 58 | +### Type Checking |
| 59 | +```bash |
| 60 | +make typecheck |
| 61 | +``` |
| 62 | +- Runs `pyright` on both workspaces separately |
| 63 | +- CircuitPython workspace: uses custom typeshed stubs |
| 64 | +- CPython workspace: uses standard library type hints |
| 65 | +- **Zero tolerance** for `# type: ignore` in flight software (except for documented upstream bugs with PR links) |
| 66 | + |
| 67 | +**Expected time**: 15-30 seconds |
| 68 | + |
| 69 | +### Testing |
| 70 | +```bash |
| 71 | +make test |
| 72 | +``` |
| 73 | +- Runs pytest on `cpython-workspaces/flight-software-unit-tests/src` |
| 74 | +- Generates coverage reports in `.coverage-reports/` |
| 75 | +- **Target**: 100% code coverage |
| 76 | +- Uses `coverage` with branch coverage enabled |
| 77 | + |
| 78 | +**Expected time**: 20-40 seconds |
| 79 | + |
| 80 | +### Documentation (Local Preview) |
| 81 | +```bash |
| 82 | +make docs |
| 83 | +``` |
| 84 | +- Serves documentation locally at `http://localhost:8000` |
| 85 | +- Uses MkDocs with Material theme |
| 86 | +- Auto-reloads on file changes |
| 87 | + |
| 88 | +### Cleaning Build Artifacts |
| 89 | +```bash |
| 90 | +make clean |
| 91 | +``` |
| 92 | +- Removes all git-ignored files (`.venv`, `.coverage-reports`, `tools/`, etc.) |
| 93 | +- Use when environment is corrupted or dependencies need fresh install |
| 94 | + |
| 95 | +## CI/CD Pipeline (GitHub Actions) |
| 96 | + |
| 97 | +The repository runs three parallel CI jobs on all PRs and pushes to `main`: |
| 98 | + |
| 99 | +1. **Lint** (`.github/workflows/ci.yaml`): |
| 100 | + - Runs `make fmt` |
| 101 | + - **Failure**: Code style violations, missing trailing newlines, `# type: ignore` in flight-software |
| 102 | + |
| 103 | +2. **Typecheck**: |
| 104 | + - Runs `make typecheck` |
| 105 | + - **Failure**: Type errors in either workspace, missing type hints |
| 106 | + |
| 107 | +3. **Test**: |
| 108 | + - Runs `TEST_SELECT=ALL make test` |
| 109 | + - Uploads coverage to SonarQube |
| 110 | + - **Failure**: Test failures, coverage regression |
| 111 | + |
| 112 | +**All three must pass** before merging. Always run these commands locally before pushing. |
| 113 | + |
| 114 | +## Project Layout & Architecture |
| 115 | + |
| 116 | +### Root Directory Files |
| 117 | +``` |
| 118 | +.devcontainer/ # Dev container configuration for VS Code |
| 119 | +.github/workflows/ # CI/CD workflows (ci.yaml, docs.yaml) |
| 120 | +.vscode/ # VS Code workspace settings |
| 121 | +circuitpython-workspaces/ # CircuitPython code |
| 122 | +cpython-workspaces/ # CPython code (tests, mocks) |
| 123 | +docs/ # MkDocs documentation |
| 124 | +Makefile # Build commands |
| 125 | +pyproject.toml # Root workspace configuration |
| 126 | +pysquared.code-workspace # VS Code workspace file (ALWAYS use this) |
| 127 | +.pre-commit-config.yaml # Pre-commit hook definitions |
| 128 | +mkdocs.yaml # Documentation build configuration |
| 129 | +uv.lock # Locked dependencies |
| 130 | +``` |
| 131 | + |
| 132 | +### Flight Software Structure (`circuitpython-workspaces/flight-software/src/pysquared/`) |
| 133 | +``` |
| 134 | +pysquared/ |
| 135 | +├── __init__.py |
| 136 | +├── beacon.py # Beacon transmission logic |
| 137 | +├── binary_encoder.py # Data encoding utilities |
| 138 | +├── cdh.py # Command & Data Handling |
| 139 | +├── config/ # Configuration management (Config, RadioConfig) |
| 140 | +│ ├── config.py # Main config class (loads from JSON) |
| 141 | +│ └── radio_config.py |
| 142 | +├── detumble.py # Attitude control algorithms |
| 143 | +├── file_validation/ # File integrity checking |
| 144 | +├── hardware/ # Hardware drivers (organized by sensor type) |
| 145 | +│ ├── burnwire/ # Deployment mechanism drivers |
| 146 | +│ ├── imu/ # Inertial Measurement Unit (LSM6DS) |
| 147 | +│ ├── light_sensor/ # Light sensors (VEML7700) |
| 148 | +│ ├── load_switch/ # Power switching |
| 149 | +│ ├── magnetometer/ # Magnetometers (LIS2MDL) |
| 150 | +│ ├── power_monitor/ # Power monitoring (INA219) |
| 151 | +│ ├── radio/ # Radio drivers (RFM, SX126x, SX1280) |
| 152 | +│ ├── sd_card/ # SD card management |
| 153 | +│ └── temperature_sensor/ # Temperature sensors (MCP9808) |
| 154 | +├── logger.py # JSON-structured logging (Loguru-style API) |
| 155 | +├── nvm/ # Non-volatile memory (Counter, Flag classes) |
| 156 | +├── power_health.py # Power monitoring and battery management |
| 157 | +├── protos/ # Protocol definitions (base classes with `...`) |
| 158 | +├── rtc/ # Real-time clock management |
| 159 | +├── sensor_reading/ # Sensor data structures (SI units required) |
| 160 | +├── sleep_helper.py # Safe sleep with watchdog petting |
| 161 | +└── watchdog.py # Watchdog timer management |
| 162 | +``` |
| 163 | + |
| 164 | +**Hardware Manager Pattern**: Each hardware type has a `manager/` subdirectory containing driver implementations that implement protocols from `protos/`. |
| 165 | + |
| 166 | +### Test Structure (`cpython-workspaces/flight-software-unit-tests/src/unit-tests/`) |
| 167 | +- Mirrors flight software structure |
| 168 | +- Uses pytest fixtures extensively |
| 169 | +- Mocks hardware via `flight-software-mocks` workspace |
| 170 | + |
| 171 | +### Configuration Files |
| 172 | +- **pyproject.toml**: Python project metadata, tool configs (ruff, pytest, coverage, interrogate) |
| 173 | +- **pyrightconfig.json**: Type checker configuration (separate files for each workspace) |
| 174 | +- **.pre-commit-config.yaml**: Pre-commit hooks (ruff, codespell, custom validators) |
| 175 | +- **mkdocs.yaml**: Documentation site structure |
| 176 | + |
| 177 | +## Critical Development Guidelines |
| 178 | + |
| 179 | +### Code Style & Quality |
| 180 | +1. **Always use relative imports** in flight software: |
| 181 | + ```python |
| 182 | + from .sensors.temperature import TemperatureSensor # ✓ Correct |
| 183 | + from pysquared.sensors.temperature import ... # ✗ Wrong |
| 184 | + ``` |
| 185 | + |
| 186 | +2. **Sensor readings must be in SI units** with timestamps (see design-guide.md for full table) |
| 187 | + |
| 188 | +3. **Error handling**: Use try/except blocks, log with `logger.error()`, return default values on sensor failures |
| 189 | + |
| 190 | +4. **Avoid `typing` module in CircuitPython code** (not supported): |
| 191 | + ```python |
| 192 | + # ✗ Don't do this in circuitpython-workspaces |
| 193 | + from typing import List, Optional |
| 194 | + |
| 195 | + # ✓ Use this pattern instead |
| 196 | + try: |
| 197 | + from typing import List, Optional |
| 198 | + except ImportError: |
| 199 | + pass |
| 200 | + ``` |
| 201 | + |
| 202 | +5. **Configuration**: All config loads from JSON files (`config.json`, `jokes.json`) |
| 203 | + |
| 204 | +6. **Documentation**: All modules, classes, and functions require docstrings (enforced by interrogate) |
| 205 | + |
| 206 | +### Testing Requirements |
| 207 | +- 100% code coverage target |
| 208 | +- Use mocks from `flight-software-mocks` workspace |
| 209 | +- Test files mirror source structure: `test_<module>.py` |
| 210 | +- Use pytest fixtures for setup/teardown |
| 211 | + |
| 212 | +### VS Code Workspace Setup |
| 213 | +**ALWAYS open `pysquared.code-workspace`** in VS Code, not the raw folder. This provides: |
| 214 | +- Correct type hints for both CircuitPython and CPython code |
| 215 | +- Prevents false positives from mixing workspace type systems |
| 216 | +- Proper pyright configuration per workspace |
| 217 | + |
| 218 | +See contributing.md for detailed workspace setup instructions. |
| 219 | + |
| 220 | +## Common Issues & Workarounds |
| 221 | + |
| 222 | +### Network Dependency Installation Failures |
| 223 | +If `make` fails to download `uv` due to network issues, the build will fail. This is expected in restricted environments. The Makefile downloads `uv` from `https://astral.sh/uv/0.8.14/install.sh`. |
| 224 | + |
| 225 | +### Type Ignore Exceptions |
| 226 | +Only allowed in flight software with upstream bug links: |
| 227 | +```python |
| 228 | +variable = function() # type: ignore # PR https://github.com/org/repo/pull/123 |
| 229 | +``` |
| 230 | +Excluded files (legacy): `beacon.py`, `logger.py`, `rtc/manager/microcontroller.py`, `hardware/sd_card/manager/sd_card.py` |
| 231 | + |
| 232 | +### CircuitPython Compatibility |
| 233 | +- Python 3.4 syntax + type hints only |
| 234 | +- No `pathlib`, `asyncio` (except Adafruit's CircuitPython version), or most stdlib modules |
| 235 | +- See design-guide.md for full list of differences |
| 236 | + |
| 237 | +### Pre-commit Hook Failures |
| 238 | +If pre-commit hooks fail during commit: |
| 239 | +```bash |
| 240 | +make fmt # Auto-fixes most issues |
| 241 | +# Review remaining errors, fix manually, then commit again |
| 242 | +``` |
| 243 | + |
| 244 | +## Validation Checklist |
| 245 | + |
| 246 | +Before submitting a PR, ALWAYS run: |
| 247 | +```bash |
| 248 | +make fmt # Fix formatting |
| 249 | +make typecheck # Verify types |
| 250 | +make test # Run tests |
| 251 | +``` |
| 252 | + |
| 253 | +All three must pass with zero errors. Check the output carefully: |
| 254 | +- **fmt**: Look for "Passed" or "Failed" on each hook |
| 255 | +- **typecheck**: Should show "0 errors" for both workspaces |
| 256 | +- **test**: Should show "100% coverage" and all tests passing |
| 257 | + |
| 258 | +## Additional Resources |
| 259 | + |
| 260 | +- **Full docs**: https://proveskit.github.io/pysquared/ |
| 261 | +- **Design principles**: See `docs/design-guide.md` |
| 262 | +- **Contributing guide**: See `docs/contributing.md` |
| 263 | +- **CircuitPython docs**: https://docs.circuitpython.org/ |
| 264 | +- **PROVES hardware**: https://docs.proveskit.space/ |
| 265 | + |
| 266 | +## Trust These Instructions |
| 267 | + |
| 268 | +These instructions have been validated against the repository structure, Makefile, CI workflows, and existing documentation. **Only perform additional searches if**: |
| 269 | +1. These instructions are incomplete for your specific task |
| 270 | +2. You discover information that contradicts these instructions |
| 271 | +3. You need details about specific hardware drivers or sensors not covered here |
| 272 | + |
| 273 | +For most code changes, linting, testing, and validation tasks, trust these instructions and proceed directly to implementation. |
0 commit comments