From fdd800e6dac4e6b7817002b2309fafca2143f5f7 Mon Sep 17 00:00:00 2001 From: Gui-FernandesBR Date: Sat, 14 Mar 2026 14:47:20 -0300 Subject: [PATCH] ENH: Add guidelines for simulation safety, Sphinx documentation, and pytest standards (GitHub Copilot) --- .github/agents/rocketpy-reviewer.agent.md | 62 ++++ .github/copilot-instructions.md | 301 +++++------------- .../simulation-safety.instructions.md | 41 +++ .../instructions/sphinx-docs.instructions.md | 32 ++ .../instructions/tests-python.instructions.md | 36 +++ 5 files changed, 251 insertions(+), 221 deletions(-) create mode 100644 .github/agents/rocketpy-reviewer.agent.md create mode 100644 .github/instructions/simulation-safety.instructions.md create mode 100644 .github/instructions/sphinx-docs.instructions.md create mode 100644 .github/instructions/tests-python.instructions.md diff --git a/.github/agents/rocketpy-reviewer.agent.md b/.github/agents/rocketpy-reviewer.agent.md new file mode 100644 index 000000000..be1b64b13 --- /dev/null +++ b/.github/agents/rocketpy-reviewer.agent.md @@ -0,0 +1,62 @@ +--- +description: "Physics-safe RocketPy code review agent. Use for pull request review, unit consistency checks, coordinate-frame validation, cached-property risk detection, and regression-focused test-gap analysis." +name: "RocketPy Reviewer" +tools: [read, search, execute] +argument-hint: "Review these changes for physics correctness and regression risk: " +user-invocable: true +--- +You are a RocketPy-focused reviewer for physics safety and regression risk. + +## Goals + +- Detect behavioral regressions and numerical/physics risks before merge. +- Validate unit consistency and coordinate/reference-frame correctness. +- Identify stale-cache risks when `@cached_property` interacts with mutable state. +- Check test coverage quality for changed behavior. +- Verify alignment with RocketPy workflow and contributor conventions. + +## Review Priorities + +1. Correctness and safety issues (highest severity). +2. Behavioral regressions and API compatibility. +3. Numerical stability and tolerance correctness. +4. Missing tests or weak assertions. +5. Documentation mismatches affecting users. +6. Workflow violations (test placement, branch/PR conventions, or missing validation evidence). + +## RocketPy-Specific Checks + +- SI units are explicit and consistent. +- Orientation conventions are unambiguous (`tail_to_nose`, `nozzle_to_combustion_chamber`, etc.). +- New/changed simulation logic does not silently invalidate cached values. +- Floating-point assertions use `pytest.approx` where needed. +- New fixtures are wired through `tests/conftest.py` when applicable. +- Test type is appropriate for scope (`unit`, `integration`, `acceptance`) and `all_info()`-style tests + are not misclassified. +- New behavior includes at least one regression-oriented test and relevant edge-case checks. +- For docs-affecting changes, references and paths remain valid and build warnings are addressed. +- Tooling recommendations match current repository setup (prefer Makefile plus `pyproject.toml` + settings when docs are outdated). + +## Validation Expectations + +- Prefer focused test runs first, then broader relevant suites. +- Recommend `make format` and `make lint` when style/lint risks are present. +- Recommend `make build-docs` when `.rst` files or API docs are changed. + +## Output Format + +Provide findings first, ordered by severity. +For each finding include: +- Severity: Critical, High, Medium, or Low +- Location: file path and line +- Why it matters: behavioral or physics risk +- Suggested fix: concrete, minimal change + +After findings, include: +- Open questions or assumptions +- Residual risks or testing gaps +- Brief change summary +- Suggested validation commands (only when useful) + +If no findings are identified, state that explicitly and still report residual risks/testing gaps. diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index f5366cb3b..382aa15e0 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -1,221 +1,80 @@ -# GitHub Copilot Instructions for RocketPy - -This file provides instructions for GitHub Copilot when working on the RocketPy codebase. -These guidelines help ensure consistency with the project's coding standards and development practices. - -## Project Overview - -RocketPy is a Python library for 6-DOF rocket trajectory simulation. -It's designed for high-power rocketry applications with focus on accuracy, performance, and ease of use. - -## Coding Standards - -### Naming Conventions -- **Use `snake_case` for all new code** - variables, functions, methods, and modules -- **Use descriptive names** - prefer `angle_of_attack` over `a` or `alpha` -- **Class names use PascalCase** - e.g., `SolidMotor`, `Environment`, `Flight` -- **Constants use UPPER_SNAKE_CASE** - e.g., `DEFAULT_GRAVITY`, `EARTH_RADIUS` - -### Code Style -- Follow **PEP 8** guidelines -- Line length: **88 characters** (Black's default) -- Organize imports with **isort** -- Our official formatter is the **ruff frmat** - -### Documentation -- **All public classes, methods, and functions must have docstrings** -- Use **NumPy style docstrings** -- Include **Parameters**, **Returns**, and **Examples** sections -- Document **units** for physical quantities (e.g., "in meters", "in radians") - -### Testing -- Write **unit tests** for all new features using pytest -- Follow **AAA pattern** (Arrange, Act, Assert) -- Use descriptive test names following: `test_methodname_expectedbehaviour` -- Include test docstrings explaining expected behavior -- Use **parameterization** for testing multiple scenarios -- Create pytest fixtures to avoid code repetition - -## Domain-Specific Guidelines - -### Physical Units and Conventions -- **SI units by default** - meters, kilograms, seconds, radians -- **Document coordinate systems** clearly (e.g., "tail_to_nose", "nozzle_to_combustion_chamber") -- **Position parameters** are critical - always document reference points -- Use **descriptive variable names** for physical quantities - -### Rocket Components -- **Motors**: SolidMotor, HybridMotor and LiquidMotor classes are children classes of the Motor class -- **Aerodynamic Surfaces**: They have Drag curves and lift coefficients -- **Parachutes**: Trigger functions, deployment conditions -- **Environment**: Atmospheric models, weather data, wind profiles - -### Mathematical Operations -- Use **numpy arrays** for vectorized operations (this improves performance) -- Prefer **scipy functions** for numerical integration and optimization -- **Handle edge cases** in calculations (division by zero, sqrt of negative numbers) -- **Validate input ranges** for physical parameters -- Monte Carlo simulations: sample from `numpy.random` for random number generation and creates several iterations to assess uncertainty in simulations. - -## File Structure and Organization - -### Source Code Organization - -Reminds that `rocketpy` is a Python package served as a library, and its source code is organized into several modules to facilitate maintainability and clarity. The following structure is recommended: - -``` -rocketpy/ -├── core/ # Core simulation classes -├── motors/ # Motor implementations -├── environment/ # Atmospheric and environmental models -├── plots/ # Plotting and visualization -├── tools/ # Utility functions -└── mathutils/ # Mathematical utilities -``` - -Please refer to popular Python packages like `scipy`, `numpy`, and `matplotlib` for inspiration on module organization. - -### Test Organization -``` -tests/ -├── unit/ # Unit tests -├── integration/ # Integration tests -├── acceptance/ # Acceptance tests -└── fixtures/ # Test fixtures organized by component -``` - -### Documentation Structure -``` -docs/ -├── user/ # User guides and tutorials -├── development/ # Development documentation -├── reference/ # API reference -├── examples/ # Flight examples and notebooks -└── technical/ # Technical documentation -``` - -## Common Patterns and Practices - -### Error Handling -- Use **descriptive error messages** with context -- **Validate inputs** at class initialization and method entry -- Raise **appropriate exception types** (ValueError, TypeError, etc.) -- Include **suggestions for fixes** in error messages - -### Performance Considerations -- Use **vectorized operations** where possible -- **Cache expensive computations** when appropriate (we frequently use `cached_property`) -- Keep in mind that RocketPy must be fast! - -### Backward Compatibility -- **Avoid breaking changes** in public APIs -- Use **deprecation warnings** before removing features -- **Document code changes** in docstrings and CHANGELOG - -## AI Assistant Guidelines - -### Code Generation -- **Always include docstrings** for new functions and classes -- **Follow existing patterns** in the codebase -- **Consider edge cases** and error conditions - -### Code Review and Suggestions -- **Check for consistency** with existing code style -- **Verify physical units** and coordinate systems -- **Ensure proper error handling** and input validation -- **Suggest performance improvements** when applicable -- **Recommend additional tests** for new functionality - -### Documentation Assistance -- **Use NumPy docstring format** consistently -- **Include practical examples** in docstrings -- **Document physical meanings** of parameters -- **Cross-reference related functions** and classes - -## Testing Guidelines - -### Unit Tests -- **Test individual methods** in isolation -- **Use fixtures** from the appropriate test fixture modules -- **Mock external dependencies** when necessary -- **Test both happy path and error conditions** - -### Integration Tests -- **Test interactions** between components -- **Verify end-to-end workflows** (Environment → Motor → Rocket → Flight) - -### Test Data -- **Use realistic parameters** for rocket simulations -- **Include edge cases** (very small/large rockets, extreme conditions) -- **Test with different coordinate systems** and orientations - -## Project-Specific Considerations - -### User Experience -- **Provide helpful error messages** with context and suggestions -- **Include examples** in docstrings and documentation -- **Support common use cases** with reasonable defaults - -## Examples of Good Practices - -### Function Definition -```python -def calculate_drag_force( - velocity, - air_density, - drag_coefficient, - reference_area -): - """Calculate drag force using the standard drag equation. - - Parameters - ---------- - velocity : float - Velocity magnitude in m/s. - air_density : float - Air density in kg/m³. - drag_coefficient : float - Dimensionless drag coefficient. - reference_area : float - Reference area in m². - - Returns - ------- - float - Drag force in N. - - Examples - -------- - >>> drag_force = calculate_drag_force(100, 1.225, 0.5, 0.01) - >>> print(f"Drag force: {drag_force:.2f} N") - """ - if velocity < 0: - raise ValueError("Velocity must be non-negative") - if air_density <= 0: - raise ValueError("Air density must be positive") - if reference_area <= 0: - raise ValueError("Reference area must be positive") - - return 0.5 * air_density * velocity**2 * drag_coefficient * reference_area -``` - -### Test Example -```python -def test_calculate_drag_force_returns_correct_value(): - """Test drag force calculation with known inputs.""" - # Arrange - velocity = 100.0 # m/s - air_density = 1.225 # kg/m³ - drag_coefficient = 0.5 - reference_area = 0.01 # m² - expected_force = 30.625 # N - - # Act - result = calculate_drag_force(velocity, air_density, drag_coefficient, reference_area) - - # Assert - assert abs(result - expected_force) < 1e-6 -``` - - -Remember: RocketPy prioritizes accuracy, performance, and usability. Always consider the physical meaning of calculations and provide clear, well-documented interfaces for users. +# RocketPy Workspace Instructions + +## Code Style +- Use snake_case for variables, functions, methods, and modules. Use descriptive names. +- Use PascalCase for classes and UPPER_SNAKE_CASE for constants. +- Keep lines at 88 characters and follow PEP 8 unless existing code in the target file differs. +- Run Ruff as the source of truth for formatting/import organization: + - `make format` + - `make lint` +- Use NumPy-style docstrings for public classes, methods, and functions, including units. +- In case of tooling drift between docs and config, prefer current repository tooling in `Makefile` + and `pyproject.toml`. + +## Architecture +- RocketPy is a modular Python library; keep feature logic in the correct package boundary: + - `rocketpy/simulation`: flight simulation and Monte Carlo orchestration. + - `rocketpy/rocket`, `rocketpy/motors`, `rocketpy/environment`: domain models. + - `rocketpy/mathutils`: numerical primitives and interpolation utilities. + - `rocketpy/plots`, `rocketpy/prints`: output and visualization layers. +- Prefer extending existing classes/patterns over introducing new top-level abstractions. +- Preserve public API stability in `rocketpy/__init__.py` exports. + +## Build and Test +- Use Makefile targets for OS-agnostic workflows: + - `make install` + - `make pytest` + - `make pytest-slow` + - `make coverage` + - `make coverage-report` + - `make build-docs` +- Before finishing code changes, run focused tests first, then broader relevant suites. +- When running Python directly in this workspace, prefer `.venv/Scripts/python.exe`. +- Slow tests are explicitly marked with `@pytest.mark.slow` and are run with `make pytest-slow`. +- For docs changes, check `make build-docs` output and resolve warnings/errors when practical. + +## Development Workflow +- Target pull requests to `develop` by default; `master` is the stable branch. +- Use branch names in `type/description` format, such as: + - `bug/` + - `doc/` + - `enh/` + - `mnt/` + - `tst/` +- Prefer rebasing feature branches on top of `develop` to keep history linear. +- Keep commit and PR titles explicit and prefixed with project acronyms when possible: + - `BUG`, `DOC`, `ENH`, `MNT`, `TST`, `BLD`, `REL`, `REV`, `STY`, `DEV`. + +## Conventions +- SI units are the default. Document units and coordinate-system references explicitly. +- Position/reference-frame arguments are critical in this codebase. Be explicit about orientation + (for example, `tail_to_nose`, `nozzle_to_combustion_chamber`). +- Include unit tests for new behavior. Follow AAA structure and clear test names. +- Use fixtures from `tests/fixtures`; if adding a new fixture module, update `tests/conftest.py`. +- Use `pytest.approx` for floating-point checks where appropriate. +- Use `@cached_property` for expensive computations when helpful, and be careful with stale-cache + behavior when underlying mutable state changes. +- Keep behavior backward compatible across the public API exported via `rocketpy/__init__.py`. +- Prefer extending existing module patterns over creating new top-level package structure. + +## Testing Taxonomy +- Unit tests are mandatory for new behavior. +- Unit tests in RocketPy can be sociable (real collaborators allowed) but should still be fast and + method-focused. +- Treat tests as integration tests when they are strongly I/O-oriented or broad across many methods, + including `all_info()` convention cases. +- Acceptance tests represent realistic user/flight scenarios and may compare simulation thresholds to + known flight data. + +## Documentation Links +- Contributor workflow and setup: `docs/development/setting_up.rst` +- Style and naming details: `docs/development/style_guide.rst` +- Testing philosophy and structure: `docs/development/testing.rst` +- API reference conventions: `docs/reference/index.rst` +- Domain/physics background: `docs/technical/index.rst` + +## Scoped Customizations +- Simulation-specific rules: `.github/instructions/simulation-safety.instructions.md` +- Test-authoring rules: `.github/instructions/tests-python.instructions.md` +- RST/Sphinx documentation rules: `.github/instructions/sphinx-docs.instructions.md` +- Specialized review persona: `.github/agents/rocketpy-reviewer.agent.md` diff --git a/.github/instructions/simulation-safety.instructions.md b/.github/instructions/simulation-safety.instructions.md new file mode 100644 index 000000000..cc2af5d27 --- /dev/null +++ b/.github/instructions/simulation-safety.instructions.md @@ -0,0 +1,41 @@ +--- +description: "Use when editing rocketpy/simulation code, including Flight state updates, Monte Carlo orchestration, post-processing, or cached computations. Covers simulation state safety, unit/reference-frame clarity, and regression checks." +name: "Simulation Safety" +applyTo: "rocketpy/simulation/**/*.py" +--- +# Simulation Safety Guidelines + +- Keep simulation logic inside `rocketpy/simulation` and avoid leaking domain behavior that belongs in + `rocketpy/rocket`, `rocketpy/motors`, or `rocketpy/environment`. +- Preserve public API behavior and exported names used by `rocketpy/__init__.py`. +- Prefer extending existing simulation components before creating new abstractions: + - `flight.py`: simulation state, integration flow, and post-processing. + - `monte_carlo.py`: orchestration and statistical execution workflows. + - `flight_data_exporter.py` and `flight_data_importer.py`: persistence and interchange. + - `flight_comparator.py`: comparative analysis outputs. +- Be explicit with physical units and reference frames in new parameters, attributes, and docstrings. +- For position/orientation-sensitive behavior, use explicit conventions (for example + `tail_to_nose`, `nozzle_to_combustion_chamber`) and avoid implicit assumptions. +- Treat state mutation carefully when cached values exist. +- If changes can invalidate `@cached_property` values, either avoid post-computation mutation or + explicitly invalidate affected caches in a controlled, documented way. +- Keep numerical behavior deterministic unless stochastic behavior is intentional and documented. +- For Monte Carlo and stochastic code paths, make randomness controllable and reproducible when tests + rely on it. +- Prefer vectorized NumPy operations for hot paths and avoid introducing Python loops in + performance-critical sections without justification. +- Guard against numerical edge cases (zero/near-zero denominators, interpolation limits, and boundary + conditions). +- Do not change default numerical tolerances or integration behavior without documenting motivation and + validating regression impact. +- Add focused regression tests for changed behavior, including edge cases and orientation-dependent + behavior. +- For floating-point expectations, use `pytest.approx` with meaningful tolerances. +- Run focused tests first, then broader relevant tests (`make pytest` and `make pytest-slow` when + applicable). + +See: +- `docs/development/testing.rst` +- `docs/development/style_guide.rst` +- `docs/development/setting_up.rst` +- `docs/technical/index.rst` diff --git a/.github/instructions/sphinx-docs.instructions.md b/.github/instructions/sphinx-docs.instructions.md new file mode 100644 index 000000000..8c24cac53 --- /dev/null +++ b/.github/instructions/sphinx-docs.instructions.md @@ -0,0 +1,32 @@ +--- +description: "Use when writing or editing docs/**/*.rst. Covers Sphinx/reStructuredText conventions, cross-references, toctree hygiene, and RocketPy unit/reference-frame documentation requirements." +name: "Sphinx RST Conventions" +applyTo: "docs/**/*.rst" +--- +# Sphinx and RST Guidelines + +- Follow existing heading hierarchy and style in the target document. +- Prefer linking to existing documentation pages instead of duplicating content. +- Use Sphinx cross-references where appropriate (`:class:`, `:func:`, `:mod:`, `:doc:`, `:ref:`). +- Keep API names and module paths consistent with current code exports. +- Document physical units and coordinate/reference-frame conventions explicitly. +- Include concise, practical examples when introducing new user-facing behavior. +- Keep prose clear and technical; avoid marketing language in development/reference docs. +- When adding a new page, update the relevant `toctree` so it appears in navigation. +- Use RocketPy docs build workflow: + - `make build-docs` from repository root for normal validation. + - If stale artifacts appear, clean docs build outputs via `cd docs && make clean`, then rebuild. +- Treat new Sphinx warnings/errors as issues to fix or explicitly call out in review notes. +- Keep `docs/index.rst` section structure coherent with user, development, reference, technical, and + examples navigation. +- Do not edit Sphinx-generated scaffolding files unless explicitly requested: + - `docs/Makefile` + - `docs/make.bat` +- For API docs, ensure references remain aligned with exported/public objects and current module paths. + +See: +- `docs/index.rst` +- `docs/development/build_docs.rst` +- `docs/development/style_guide.rst` +- `docs/reference/index.rst` +- `docs/technical/index.rst` diff --git a/.github/instructions/tests-python.instructions.md b/.github/instructions/tests-python.instructions.md new file mode 100644 index 000000000..1e9626142 --- /dev/null +++ b/.github/instructions/tests-python.instructions.md @@ -0,0 +1,36 @@ +--- +description: "Use when creating or editing pytest files in tests/. Enforces AAA structure, naming conventions, fixture usage, parameterization, slow-test marking, and numerical assertion practices for RocketPy." +name: "RocketPy Pytest Standards" +applyTo: "tests/**/*.py" +--- +# RocketPy Test Authoring Guidelines + +- Unit tests are mandatory for new behavior. +- Follow AAA structure in each test: Arrange, Act, Assert. +- Use descriptive test names matching project convention: + - `test_methodname` + - `test_methodname_stateundertest` + - `test_methodname_expectedbehaviour` +- Include docstrings that clearly state expected behavior and context. +- Prefer parameterization for scenario matrices instead of duplicated tests. +- Classify tests correctly: + - `tests/unit`: fast, method-focused tests (sociable unit tests are acceptable in RocketPy). + - `tests/integration`: broad multi-method/component interactions and strongly I/O-oriented cases. + - `tests/acceptance`: realistic end-user/flight scenarios with threshold-based expectations. +- By RocketPy convention, tests centered on `all_info()` behavior are integration tests. +- Reuse fixtures from `tests/fixtures` whenever possible. +- Keep fixture organization aligned with existing categories under `tests/fixtures` + (environment, flight, motor, rockets, surfaces, units, etc.). +- If you add a new fixture module, update `tests/conftest.py` so fixtures are discoverable. +- Keep tests deterministic: set seeds when randomness is involved and avoid unstable external + dependencies unless integration behavior explicitly requires them. +- Use `pytest.approx` for floating-point comparisons with realistic tolerances. +- Mark expensive tests with `@pytest.mark.slow` and ensure they can run under the project slow-test + workflow. +- Include at least one negative or edge-case assertion for new behaviors. +- When adding a bug fix, include a regression test that fails before the fix and passes after it. + +See: +- `docs/development/testing.rst` +- `docs/development/style_guide.rst` +- `docs/development/setting_up.rst`