rms-polymath 2.1.1__tar.gz → 2.3.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/.claude/rules/dependency_management.md +2 -1
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/.claude/rules/doc_python.md +42 -24
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/.claude/rules/environment.md +1 -1
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/.claude/rules/logging.md +1 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/.claude/rules/python.md +30 -21
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/.claude/rules/python_testing.md +9 -7
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/.claude/rules/security.md +1 -2
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/.claude/skills/bug-report/SKILL.md +4 -3
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/.claude/skills/critique-documentation/SKILL.md +15 -15
- rms_polymath-2.1.1/.claude/rules/doc_dev_guide.md → rms_polymath-2.3.0/.claude/skills/doc-dev-guide/SKILL.md +13 -15
- rms_polymath-2.1.1/.claude/rules/doc_how_to.md → rms_polymath-2.3.0/.claude/skills/doc-how-to/SKILL.md +5 -7
- rms_polymath-2.1.1/.claude/rules/doc_readme.md → rms_polymath-2.3.0/.claude/skills/doc-readme/SKILL.md +2 -3
- rms_polymath-2.1.1/.claude/rules/doc_user_guide.md → rms_polymath-2.3.0/.claude/skills/doc-user-guide/SKILL.md +3 -5
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/.claude/skills/git-workflow/SKILL.md +1 -1
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/.claude/skills/pull-request/SKILL.md +6 -8
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/.claude/skills/python-codebase-analysis/SKILL.md +10 -10
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/.claude/skills/python-codebase-analysis/reference.md +34 -17
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/.claude/skills/run-all-checks/SKILL.md +46 -23
- rms_polymath-2.3.0/.codespell-dictionary.txt +9 -0
- rms_polymath-2.3.0/.github/dependabot.yml +11 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/.github/workflows/publish_to_pypi.yml +2 -2
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/.github/workflows/publish_to_test_pypi.yml +2 -2
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/.github/workflows/run-tests.yml +18 -10
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/.readthedocs.yaml +2 -0
- rms_polymath-2.3.0/.vscode/settings.json +9 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/CLAUDE.md +16 -12
- rms_polymath-2.3.0/CONTRIBUTING.md +140 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/PKG-INFO +8 -3
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/README.md +3 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/critiques/2026-08-09-code-critique.md +1 -1
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/docs/conf.py +3 -3
- rms_polymath-2.3.0/docs/contributing.rst +13 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/docs/dev_guide/dev_guide_environment.rst +31 -18
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/docs/dev_guide/dev_guide_extensions.rst +2 -2
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/docs/dev_guide/dev_guide_layout.rst +5 -1
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/docs/index.rst +1 -1
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/docs/make.bat +35 -35
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/pyproject.toml +39 -14
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/scripts/read-docs.sh +5 -5
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/scripts/run-all-checks.sh +117 -38
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/src/polymath/_version.py +3 -3
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/src/polymath/boolean.py +1 -1
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/src/polymath/extensions/deriv_ops.py +2 -2
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/src/polymath/extensions/indexer.py +1 -1
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/src/polymath/extensions/math_ops.py +16 -10
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/src/polymath/extensions/readonly_ops.py +6 -6
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/src/polymath/extensions/unit_ops.py +1 -1
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/src/polymath/extensions/vector_ops.py +30 -15
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/src/polymath/matrix.py +1 -1
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/src/polymath/matrix3.py +2 -2
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/src/polymath/polynomial.py +2 -2
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/src/polymath/quaternion.py +1 -1
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/src/polymath/scalar.py +27 -13
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/src/rms_polymath.egg-info/PKG-INFO +8 -3
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/src/rms_polymath.egg-info/SOURCES.txt +9 -8
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/src/rms_polymath.egg-info/requires.txt +1 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/src/rms_polymath.egg-info/scm_file_list.json +9 -8
- rms_polymath-2.3.0/src/rms_polymath.egg-info/scm_version.json +8 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_matrix3.py +25 -14
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_matrix3_euler.py +1 -1
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_matrix_comprehensive.py +2 -2
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_pair.py +24 -21
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_polynomial_arithmetic.py +6 -6
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_polynomial_basic.py +14 -8
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_polynomial_operations.py +62 -45
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_qube_coverage.py +6 -6
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_qube_ext_item_ops.py +18 -12
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_qube_ext_mask_ops.py +6 -6
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_qube_ext_math_ops.py +14 -14
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_qube_ext_pickler.py +43 -51
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_qube_ext_shrinker.py +49 -129
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_qube_ext_tvl.py +19 -15
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_qube_ext_vector_ops.py +41 -78
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_qube_identity.py +1 -1
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_qube_new_from_parts.py +1 -1
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_qube_reshaping.py +13 -9
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_qube_unit.py +28 -28
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_scalar_comprehensive.py +8 -4
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_scalar_coverage.py +12 -7
- rms_polymath-2.3.0/tests/test_scalar_empty_reductions.py +144 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_units.py +14 -7
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_vector3_basic.py +35 -30
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_vector_comprehensive.py +4 -2
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_vector_reciprocal.py +8 -2
- rms_polymath-2.1.1/.claude/rules/documentation.md +0 -64
- rms_polymath-2.1.1/.claude/rules/how_to.md +0 -76
- rms_polymath-2.1.1/.github/workflows/audit.yml +0 -42
- rms_polymath-2.1.1/CONTRIBUTING.md +0 -108
- rms_polymath-2.1.1/docs/contributing.rst +0 -8
- rms_polymath-2.1.1/src/rms_polymath.egg-info/scm_version.json +0 -8
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/.claude/rules/filecache.md +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/.claude/skills/critique-test-suite/SKILL.md +0 -0
- {rms_polymath-2.1.1/.vscode → rms_polymath-2.3.0/.cursor}/settings.json +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/.flake8 +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/.github/ISSUE_TEMPLATE/other.md +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/.github/pull_request_template.md +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/.gitignore +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/.stubtest-allowlist +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/CODE_OF_CONDUCT.md +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/LICENSE +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/codecov.yml +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/critiques/2026-08-10-performance-critique.md +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/docs/Makefile +0 -0
- /rms_polymath-2.1.1/docs/CODE_OF_CONDUCT.md → /rms_polymath-2.3.0/docs/code_of_conduct.md +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/docs/dev_guide/dev_guide.rst +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/docs/dev_guide/dev_guide_architecture.rst +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/docs/dev_guide/dev_guide_conventions.rst +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/docs/dev_guide/dev_guide_extending.rst +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/docs/dev_guide/dev_guide_internal_api.rst +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/docs/dev_guide/dev_guide_introduction.rst +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/docs/dev_guide/dev_guide_subclasses.rst +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/docs/dev_guide/dev_guide_typing.rst +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/docs/module.rst +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/docs/user_guide/user_guide.rst +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/docs/user_guide/user_guide_derivatives.rst +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/docs/user_guide/user_guide_indexing.rst +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/docs/user_guide/user_guide_introduction.rst +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/docs/user_guide/user_guide_masks.rst +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/docs/user_guide/user_guide_math.rst +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/docs/user_guide/user_guide_objects.rst +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/docs/user_guide/user_guide_pickling.rst +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/docs/user_guide/user_guide_typing.rst +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/docs/user_guide/user_guide_units.rst +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/icons/link.png +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/requirements.txt +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/scripts/setup-venv.sh +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/setup.cfg +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/src/polymath/__init__.py +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/src/polymath/__init__.pyi +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/src/polymath/extensions/__init__.py +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/src/polymath/extensions/attr_ops.py +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/src/polymath/extensions/broadcaster.py +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/src/polymath/extensions/casting.py +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/src/polymath/extensions/dtypes.py +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/src/polymath/extensions/errors.py +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/src/polymath/extensions/item_ops.py +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/src/polymath/extensions/iterator.py +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/src/polymath/extensions/mask_ops.py +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/src/polymath/extensions/masking.py +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/src/polymath/extensions/pickler.py +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/src/polymath/extensions/shaper.py +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/src/polymath/extensions/shrinker.py +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/src/polymath/extensions/tvl.py +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/src/polymath/pair.py +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/src/polymath/py.typed +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/src/polymath/qube.py +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/src/polymath/typedefs.py +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/src/polymath/typedefs.pyi +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/src/polymath/unit.py +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/src/polymath/vector.py +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/src/polymath/vector3.py +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/src/rms_polymath.egg-info/dependency_links.txt +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/src/rms_polymath.egg-info/top_level.txt +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/__init__.py +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_boolean.py +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_indices.py +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_math_ops_coverage.py +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_matrix3_as_matrix3_validation.py +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_matrix3_deriv_class.py +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_matrix3_mask_non_unitary.py +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_matrix3_pickle.py +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_matrix3_precision.py +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_matrix3_quaternion.py +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_matrix3_to_unitary.py +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_matrix3_twovec.py +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_matrix_column_vectors.py +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_matrix_inverse.py +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_matrix_is_diagonal.py +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_matrix_misc.py +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_matrix_ops.py +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_matrix_row_vectors.py +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_matrix_solve.py +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_pair_as_pair.py +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_pair_clip2d.py +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_pair_misc.py +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_pair_swapxy.py +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_quaternion.py +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_quaternion_euler.py +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_quaternion_matrix3.py +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_quaternion_ops.py +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_quaternion_parts.py +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_qube_add_attr.py +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_qube_all.py +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_qube_any.py +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_qube_as_this_type.py +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_qube_cast.py +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_qube_clone.py +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_qube_derivs.py +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_qube_errstate_independence.py +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_qube_getitem.py +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_qube_getstate.py +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_qube_items.py +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_qube_iterate.py +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_qube_mask_nans_infs.py +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_qube_masking.py +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_qube_power.py +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_qube_readonly.py +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_qube_setitem.py +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_qube_shrink.py +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_qube_stack.py +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_qube_types.py +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_qube_zero.py +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_scalar_arccos.py +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_scalar_arcsin.py +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_scalar_arctan.py +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_scalar_arctan2.py +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_scalar_as_index.py +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_scalar_as_scalar.py +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_scalar_cos.py +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_scalar_exp.py +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_scalar_frac.py +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_scalar_int.py +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_scalar_log.py +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_scalar_max.py +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_scalar_maximum.py +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_scalar_mean.py +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_scalar_median.py +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_scalar_min.py +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_scalar_minimum.py +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_scalar_misc.py +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_scalar_ops.py +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_scalar_quadratic.py +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_scalar_sign.py +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_scalar_sin.py +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_scalar_sqrt.py +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_scalar_sum.py +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_scalar_tan.py +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_typedefs.py +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_vector3_advanced.py +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_vector3_misc.py +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_vector3_operations.py +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_vector3_spin.py +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_vector_as_column.py +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_vector_as_diagonal.py +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_vector_as_index.py +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_vector_as_row.py +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_vector_as_vector.py +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_vector_cross_2x2.py +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_vector_cross_3x3.py +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_vector_dot.py +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_vector_element_div.py +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_vector_element_mul.py +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_vector_int.py +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_vector_masking.py +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_vector_mean_sum.py +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_vector_norm.py +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_vector_norm_sq.py +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_vector_ops.py +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_vector_outer.py +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_vector_perp.py +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_vector_proj.py +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_vector_scalars.py +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_vector_sep.py +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_vector_to_pair.py +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_vector_ucross.py +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_vector_unit.py +0 -0
- {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_vector_with_norm.py +0 -0
|
@@ -32,7 +32,7 @@ description: Standards for declaring, installing, and maintaining Python project
|
|
|
32
32
|
|
|
33
33
|
## 5. Security and Maintenance
|
|
34
34
|
|
|
35
|
-
- Run `pip
|
|
35
|
+
- Run `pip-audit` in CI to catch known vulnerabilities.
|
|
36
36
|
- Enable automated dependency update tooling (Dependabot, Renovate).
|
|
37
37
|
- Review update PRs for breaking changes before merging.
|
|
38
38
|
- Periodically remove unused dependencies to reduce attack surface.
|
|
@@ -47,6 +47,7 @@ Consolidate all tool configuration into `pyproject.toml` where supported:
|
|
|
47
47
|
| coverage | `[tool.coverage.run]`, `[tool.coverage.report]` |
|
|
48
48
|
| mypy | `[tool.mypy]`, `[[tool.mypy.overrides]]` |
|
|
49
49
|
| ruff | `[tool.ruff]`, `[tool.ruff.lint]` — use explicit `select = [...]` for E, F, W, I, UP, B, SIM, C4, A, N, PT, RUF (see python) |
|
|
50
|
+
| codespell | `[tool.codespell]`, plus `.codespell-dictionary.txt` for the word pairs its parser requires in a separate file |
|
|
50
51
|
| setuptools_scm | `[tool.setuptools_scm]` |
|
|
51
52
|
|
|
52
53
|
Do NOT create separate config files (`.coveragerc`, `.mypy.ini`, `.flake8`, `setup.cfg`) when the tool supports `pyproject.toml`.
|
|
@@ -1,17 +1,18 @@
|
|
|
1
1
|
---
|
|
2
|
-
description: Foundation standards for documenting a Python package with Sphinx, ReadTheDocs, and docstrings; shared by the README, user-guide, dev-guide, and how-to
|
|
2
|
+
description: Foundation standards for documenting a Python package with Sphinx, ReadTheDocs, and docstrings; shared by the README, user-guide, dev-guide, and how-to skills.
|
|
3
3
|
---
|
|
4
4
|
|
|
5
5
|
# Python Documentation Foundation
|
|
6
6
|
|
|
7
7
|
This rule defines the documentation system, prose conventions, docstring
|
|
8
8
|
rules, and Sphinx build requirements that apply to **all** documentation in a
|
|
9
|
-
Python package. The companion
|
|
9
|
+
Python package. The companion skills (in `.claude/skills/`, loaded when a task
|
|
10
|
+
calls for them) build on it:
|
|
10
11
|
|
|
11
|
-
- `
|
|
12
|
-
- `
|
|
13
|
-
- `
|
|
14
|
-
- `
|
|
12
|
+
- `doc-readme` — the top-level `README`.
|
|
13
|
+
- `doc-user-guide` — the end-user manual.
|
|
14
|
+
- `doc-dev-guide` — the contributor / maintainer manual and API reference.
|
|
15
|
+
- `doc-how-to` — task-focused how-to articles.
|
|
15
16
|
|
|
16
17
|
Read this rule first; the others assume its docstring, cross-reference, prose,
|
|
17
18
|
and build requirements without repeating them.
|
|
@@ -30,11 +31,28 @@ and build requirements without repeating them.
|
|
|
30
31
|
## 2. Prose Conventions
|
|
31
32
|
|
|
32
33
|
- One space between a sentence-ending period and the next sentence.
|
|
33
|
-
- American spelling, not British
|
|
34
|
+
- American spelling, not British: `center` not `centre`, `color` not `colour`,
|
|
35
|
+
`normalize` not `normalise`. Enforced by `codespell`; see the allow-list in
|
|
36
|
+
`pyproject.toml` for the terms of art it is told to accept. A line that needs
|
|
37
|
+
a word the gate is right to flag -- a test whose subject is the misspelling,
|
|
38
|
+
an external API name -- carries an inline `codespell:ignore <word>` with the
|
|
39
|
+
reason beside it, rather than widening the allow-list for everyone.
|
|
34
40
|
- Define each domain-specific term on first use.
|
|
35
41
|
- Describe the **current** state of the software only. Never anchor prose to a
|
|
36
42
|
moment in time or to migration history: avoid "new", "legacy", "old",
|
|
37
43
|
"now", "recently", "as before", "backwards compatible", and similar framing.
|
|
44
|
+
- Do not cite issue/ticket numbers in documentation prose or in docstrings. Both
|
|
45
|
+
describe how the software behaves, not the tracker items that shaped it; issue
|
|
46
|
+
numbers belong in commit messages, PR descriptions, and (only as a supporting
|
|
47
|
+
reference, never as the whole comment) inline `#` code comments.
|
|
48
|
+
- This prohibition covers the documentation the package publishes: the README,
|
|
49
|
+
the user and developer guides, the how-to pages, and docstrings. It does not
|
|
50
|
+
cover `plans/` or `critiques/`, including their `archive/` subdirectories and
|
|
51
|
+
the README that indexes each one. Those are project records rather than
|
|
52
|
+
package documentation, and naming the issue that owns a piece of work is what
|
|
53
|
+
they are for: a plan states which issues a phase closes and which it leaves
|
|
54
|
+
open, and an archive index states which issues each retired document carried
|
|
55
|
+
forward. Cite freely there.
|
|
38
56
|
- Do not use unicode smart quotes, em-dashes, or arrows inside `.py` files
|
|
39
57
|
(they are acceptable in `.rst` and `.md`).
|
|
40
58
|
|
|
@@ -47,15 +65,15 @@ A single `conf.py` configures the whole tree. It MUST:
|
|
|
47
65
|
- Derive the version from installed package metadata (e.g.
|
|
48
66
|
`importlib.metadata.version`) rather than hard-coding a version string.
|
|
49
67
|
- Enable, at minimum, these extensions:
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
68
|
+
- `sphinx.ext.autodoc` — pull API docs from docstrings.
|
|
69
|
+
- `sphinx.ext.napoleon` — parse Google-style docstrings.
|
|
70
|
+
- `sphinx.ext.viewcode` — link API docs to highlighted source.
|
|
71
|
+
- `sphinx.ext.intersphinx` — cross-link to the docs of Python and key
|
|
72
|
+
third-party dependencies; populate `intersphinx_mapping` accordingly.
|
|
73
|
+
- `myst_parser` — include Markdown files (the `README`).
|
|
74
|
+
- A diagram extension (e.g. `sphinxcontrib.mermaid`) when the guides use
|
|
75
|
+
diagrams; configure it for headless/client-side rendering so CI needs no
|
|
76
|
+
browser.
|
|
59
77
|
- Set `source_suffix` to include both `.rst` and `.md`.
|
|
60
78
|
- Configure Napoleon for Google-style docstrings (`napoleon_google_docstring`,
|
|
61
79
|
`napoleon_use_param`, `napoleon_use_rtype`).
|
|
@@ -85,16 +103,16 @@ A single `conf.py` configures the whole tree. It MUST:
|
|
|
85
103
|
|
|
86
104
|
- EVERY mention of a code object in narrative prose MUST use the appropriate
|
|
87
105
|
Sphinx cross-reference role so it links to the API reference:
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
106
|
+
- `:class:`~package.module.Class``
|
|
107
|
+
- `:meth:`~package.module.Class.method``
|
|
108
|
+
- `:func:`~package.module.func``
|
|
109
|
+
- `:mod:`package.module``
|
|
110
|
+
- `:attr:`~package.module.Class.attr``
|
|
111
|
+
- `:data:`~package.module.NAME``
|
|
94
112
|
Use `:doc:` to link other documentation pages and `:ref:` for labeled
|
|
95
113
|
sections.
|
|
96
114
|
- Bare CamelCase or `module.symbol` text in prose is a violation, even when
|
|
97
|
-
wrapped in inline literals. Inline literals (
|
|
115
|
+
wrapped in inline literals. Inline literals (```` ``) are for YAML/JSON
|
|
98
116
|
keys, file paths, CLI tokens, environment variables, and shell snippets —
|
|
99
117
|
not for API symbols.
|
|
100
118
|
- Cross-references are NOT required (and should be omitted) inside
|
|
@@ -128,4 +146,4 @@ sphinx-build -n -b html docs docs/_build # nitpicky (catches broken xrefs)
|
|
|
128
146
|
- NEVER leave stale or contradictory documentation. If a feature is removed,
|
|
129
147
|
remove its documentation; if it is renamed, rename every reference.
|
|
130
148
|
- A new public module requires a corresponding API-reference entry so it
|
|
131
|
-
appears in the rendered API surface (see `
|
|
149
|
+
appears in the rendered API surface (see the `doc-dev-guide` skill).
|
|
@@ -12,7 +12,7 @@ description: Git, CI/CD (GitHub Actions), virtual environments, and tooling for
|
|
|
12
12
|
## 2. CI/CD
|
|
13
13
|
|
|
14
14
|
- ALWAYS use **GitHub Actions** for continuous integration and publishing.
|
|
15
|
-
- The local check runner (`scripts/run-all-checks.sh`, Section 3) is the **single source of truth** for which checks the repository runs. CI/CD MUST run the same set of checks the script enables -- no more, no less -- so that the AI, CI/CD, and the script stay consistent. A typical set is lint (`ruff`), type-check (`mypy`), test (`pytest`), Markdown lint (`PyMarkdown`), and documentation build (`sphinx-build`); the repository's actual enabled set is whatever the script defines. If a check is not enabled in the script, CI/CD does not run it either.
|
|
15
|
+
- The local check runner (`scripts/run-all-checks.sh`, Section 3) is the **single source of truth** for which checks the repository runs. CI/CD MUST run the same set of checks the script enables -- no more, no less -- so that the AI, CI/CD, and the script stay consistent. A typical set is lint (`ruff`), type-check (`mypy`), test (`pytest`), spell check (`codespell`), Markdown lint (`PyMarkdown`), and documentation build (`sphinx-build`); the repository's actual enabled set is whatever the script defines. If a check is not enabled in the script, CI/CD does not run it either.
|
|
16
16
|
- Every PR MUST pass that set of checks before merge.
|
|
17
17
|
- When the enabled set changes, change it in the script first, then bring CI/CD into step with it in the same change.
|
|
18
18
|
- Pin action versions to a major tag (e.g., `actions/checkout@v6`) to balance stability and security updates.
|
|
@@ -90,4 +90,5 @@ local-or-remote handling is provided by `filecache`.
|
|
|
90
90
|
| Named section + level | `with logger.open('HEADER', level='DEBUG'):` |
|
|
91
91
|
| Per-unit handlers | `with logger.open(item_id, handler=handlers):` |
|
|
92
92
|
| Exception in except block | `logger.exception('msg: %s', detail)` |
|
|
93
|
+
| Stage handler that re-raises to the orchestrator | `logger.error('msg: %s', exc)` then `raise`; the orchestrator's `exception()` records the traceback once |
|
|
93
94
|
| Standard-library logging | Only for type annotations in low-level plumbing |
|
|
@@ -14,26 +14,30 @@ Apply these rules to ALL new and modified Python code. This project is a Python
|
|
|
14
14
|
- **Module-level constants (global variables)**: Use `ALL_CAPS_WITH_UNDERSCORES`.
|
|
15
15
|
- **Private names**: Prepend a single underscore for names that are not part of the public API: private attributes (e.g. `_cache`), module-private global variables, and non-public helper functions (e.g. `_parse_header`). Public API names have no leading underscore.
|
|
16
16
|
- **Built-in names**: Do NOT use variable or function names that shadow Python built-ins (e.g. `float`, `filter`, `id`, `list`, `type`). If you must use such a name, append a single underscore (e.g. `filter_`, `type_`).
|
|
17
|
+
- **Falsy checks**: Be explicit about what you are testing. Do NOT rely on truthiness when the intent could be ambiguous. Prefer:
|
|
18
|
+
- `if x is None:` for None checks (not `if not x:` when 0 or [] could occur).
|
|
19
|
+
- `if len(seq) == 0:` when you explicitly mean "empty sequence" and other falsy values (0, None) are not possible.
|
|
20
|
+
- For dicts: `if key in d:` then use `d[key]`; avoid `d.get(key)` when you need to distinguish "missing" from "present with a falsy value" unless that is the intent.
|
|
17
21
|
- **Explicit checks over exceptions**: Prefer explicit membership or presence checks over catching exceptions for control flow. Example: use `if "a" in b: x = b["a"]` (or a clear `get` with a sentinel) rather than `try: x = b["a"]` / `except KeyError: ...` for normal flow. Use exceptions for genuinely exceptional conditions.
|
|
18
22
|
|
|
19
23
|
## 2. General Coding
|
|
20
24
|
|
|
21
|
-
-
|
|
22
|
-
-
|
|
23
|
-
-
|
|
24
|
-
-
|
|
25
|
-
-
|
|
26
|
-
- Catch exceptions at the smallest granularity possible. Do not wrap large blocks in a single `try`/`except`.
|
|
25
|
+
- ALWAYS match the coding style of pre-existing Python files.
|
|
26
|
+
- NEVER include backwards-compatibility code unless explicitly requested.
|
|
27
|
+
- ALWAYS write simple, clear code; avoid unnecessary complexity.
|
|
28
|
+
- NEVER hardcode magic constants. Define them as module-level constants, in a config module, or via environment variables.
|
|
29
|
+
- ALWAYS catch exceptions at the smallest granularity possible. Do NOT wrap large blocks in a single `try`/`except`.
|
|
27
30
|
- **Libraries:** Let exceptions propagate unless you are adding context, converting to a library-specific exception, or the exception represents a recoverable internal state. When re-raising, use `raise ... from` to preserve the full traceback for debugging.
|
|
28
|
-
- **Applications:** Do not allow uncaught exceptions to reach the top level; use a top-level handler (e.g. in the main loop or HTTP framework) so that failures are logged and the process stays predictable. In both cases,
|
|
29
|
-
-
|
|
31
|
+
- **Applications:** Do not allow uncaught exceptions to reach the top level; use a top-level handler (e.g. in the main loop or HTTP framework) so that failures are logged and the process stays predictable. In both cases, ALWAYS provide full exception information for debugging (e.g. traceback, `raise ... from` when re-raising).
|
|
32
|
+
- ALWAYS include meaningful, structured logging that can be disabled or redirected. NEVER use bare `print()` for diagnostic output in library code.
|
|
30
33
|
- Avoid mutable global variables. If unavoidable, document purpose and limit scope. Prefer module-level constants (ALL_CAPS) or dependency injection.
|
|
31
|
-
-
|
|
32
|
-
-
|
|
33
|
-
-
|
|
34
|
-
-
|
|
34
|
+
- ALWAYS prefer comprehensions (list, dict, set, generator) over manual loops when the result is a new collection and the expression remains readable.
|
|
35
|
+
- ALWAYS make the minimal changes necessary. NEVER modify code outside the scope of the current task.
|
|
36
|
+
- ALWAYS apply DRY. NEVER duplicate code. Place reusable logic in a utility module. Search existing utilities before writing new functions. Parameterize utility functions to increase generality.
|
|
37
|
+
- ALWAYS place imports at the top of the file in three alphabetically-sorted groups separated by a blank line: (1) standard library, (2) third-party, (3) local project. When adding new code or tests, add new imports to the appropriate group at the top; do not place them adjacent to the new code. Inline imports are permitted only to avoid heavy optional dependencies (e.g., GUI libraries).
|
|
38
|
+
- Positional parameters are the values a caller naturally supplies together: one logical group, in an obvious order. Usually that is at most three, but four or five positional parameters are correct when they form a single logical unit (e.g. `self, pos_x, pos_y, pos_z`) -- NEVER split such a group with `*` just to satisfy a count. Optional and configuration parameters MUST be keyword-only (after `*`). If the leading logical group is larger than about five parameters, make all parameters (after `self`) keyword-only instead.
|
|
35
39
|
- Use the Receive-an-Object, Return-an-Object (RORO) pattern when a function takes or returns more than a few related values: accept a dataclass or TypedDict and return one, rather than long positional tuples.
|
|
36
|
-
-
|
|
40
|
+
- NEVER use `getattr` just as a defensive measure if it is guaranteed that the object has the attribute. ALWAYS reference the attribute directly unless there is a specific reason to know the attribute may not be present. NEVER use getattr to reference the result of an `argparse` namespace when the argument name is a constant string.
|
|
37
41
|
|
|
38
42
|
## 3. Public API Design
|
|
39
43
|
|
|
@@ -45,7 +49,8 @@ Apply these rules to ALL new and modified Python code. This project is a Python
|
|
|
45
49
|
## 4. Comments
|
|
46
50
|
|
|
47
51
|
- ALWAYS write self-documenting code: meaningful names, simple structure, limited nesting.
|
|
48
|
-
- NEVER
|
|
52
|
+
- NEVER write a comment whose ONLY content is a restatement of the code, a user request, or modification history. A comment must earn its place by describing behavior or rationale the code itself cannot show.
|
|
53
|
+
- An issue/ticket number is welcome AS A REFERENCE once a comment already describes the behavior or rationale. Good: `# Cap the tier when the fit is rank-deficient: an unobservable axis is an assumption, not a measurement (#221).` — it explains the behavior and cites the issue for further context. Not acceptable: `# Fix for #221.` — that is only historical.
|
|
49
54
|
- ALWAYS include comments that explain the **rationale** behind non-obvious or complex logic.
|
|
50
55
|
- ALWAYS preserve existing comments that are still accurate and relevant. Remove or update stale comments.
|
|
51
56
|
|
|
@@ -54,25 +59,29 @@ Apply these rules to ALL new and modified Python code. This project is a Python
|
|
|
54
59
|
### Types
|
|
55
60
|
|
|
56
61
|
- NEVER use type annotations in the src directory tree, with one exception. Types of input parameters and returns should be indicated in the docstrings. The exception is a property, which may carry an inline return annotation so that the rendered documentation shows the type beside the property name; a property annotated this way keeps a one-line docstring rather than a `Returns:` block.
|
|
57
|
-
-
|
|
62
|
+
- ALWAYS annotate all test function/method parameters and return values, including `-> None` for functions (and `__init__`) that return nothing.
|
|
58
63
|
- Use modern generic syntax (`list[str]`, `dict[str, int]`, `X | None`) for Python 3.11+.
|
|
59
64
|
|
|
60
65
|
### Mypy
|
|
61
66
|
|
|
62
|
-
- NEVER run `mypy` on the src directory tree.
|
|
63
|
-
-
|
|
67
|
+
- NEVER run `mypy` on the src directory tree. It is deliberately unannotated; the `exclude` patterns and `ignore_errors` overrides in `pyproject.toml` exist only so that `mypy.stubtest` can check the two published stubs against it.
|
|
68
|
+
- ALWAYS run `mypy` on the tests after changes. Fix all errors before delivering.
|
|
69
|
+
- NEVER add other global type exclusions. "Global type exclusions" means:
|
|
70
|
+
- Module-level `# type: ignore` without a specific error code.
|
|
71
|
+
- `ignore_errors = True` in mypy config.
|
|
72
|
+
- Broad `exclude` patterns that skip entire packages.
|
|
64
73
|
- In exceptional, unfixable cases use a minimal line-level ignore: `# type: ignore[error-code] # <brief justification>`.
|
|
65
74
|
|
|
66
75
|
### Ruff / Linting
|
|
67
76
|
|
|
68
|
-
-
|
|
69
|
-
-
|
|
70
|
-
- Follow PEP 8 for formatting and naming conventions.
|
|
77
|
+
- ALWAYS include `mypy` and `ruff` in the project's dev dependencies (e.g. in `pyproject.toml`).
|
|
78
|
+
- ALWAYS run `ruff check` on the full codebase after changes. Fix all errors. Do NOT run `ruff format`: the source uses deliberate column alignment that it would remove.
|
|
79
|
+
- Follow PEP 8 for all formatting and naming conventions.
|
|
71
80
|
- Use the project's explicit Ruff rule set in `pyproject.toml` (see **Ruff rule categories** below). Do not disable categories that enforce project conventions (e.g. **A** for no builtin shadowing, **N** for naming).
|
|
72
81
|
|
|
73
82
|
## 6. Docstrings
|
|
74
83
|
|
|
75
|
-
-
|
|
84
|
+
- ALWAYS include a docstring for every module, class, function, and method.
|
|
76
85
|
- Follow **PEP 257** using **Google style**. Use `Parameters:` (not `Args:`).
|
|
77
86
|
- Include `Returns:`, `Raises:`, and any important behavioral notes.
|
|
78
87
|
- NEVER mention backwards compatibility, a user request, change history, or an issue/ticket number in a docstring. Docstrings are usage documentation for the published API, not a place to explain the code's provenance; describe only observable behavior. (Issue references are allowed in inline `#` code comments per Section 4, and in commit messages and PR descriptions.)
|
|
@@ -24,8 +24,10 @@ the same standard as the package they exercise.
|
|
|
24
24
|
## 2. Framework and Tooling
|
|
25
25
|
|
|
26
26
|
- ALWAYS use `pytest`. Do not write `unittest.TestCase` classes for new tests.
|
|
27
|
-
- ALWAYS use `pytest-cov` for coverage
|
|
28
|
-
|
|
27
|
+
- ALWAYS use `pytest-cov` for coverage. `pytest-xdist` with `-n auto` should be
|
|
28
|
+
used if possible for parallelism but serial test runs may be required if the
|
|
29
|
+
code is not thread-safe. Declare appropriate options in the dev dependency
|
|
30
|
+
group.
|
|
29
31
|
- ALWAYS put type annotations on test functions (parameters and `-> None`),
|
|
30
32
|
exactly as on library code.
|
|
31
33
|
- ALWAYS write tests that are independent and order-agnostic so they are safe to
|
|
@@ -69,11 +71,11 @@ Configure pytest under `[tool.pytest.ini_options]`; do not add separate
|
|
|
69
71
|
name and scope them (`function`, `module`, `session`) to the broadest reuse
|
|
70
72
|
that is still safe.
|
|
71
73
|
- Use the built-in fixtures instead of hand-rolling isolation:
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
74
|
+
- `tmp_path` / `tmp_path_factory` for filesystem work — never write into the
|
|
75
|
+
repo or a fixed temp path.
|
|
76
|
+
- `monkeypatch` for environment variables, attributes, and `sys` state — it
|
|
77
|
+
auto-reverts after the test.
|
|
78
|
+
- `capsys` (or `capfd`) to capture and assert on stdout/stderr.
|
|
77
79
|
- If a test must mutate global or class state that no fixture manages, restore
|
|
78
80
|
the original value in a fixture teardown or a `try`/`finally` so it cannot
|
|
79
81
|
leak into other tests (critical under parallel execution).
|
|
@@ -14,7 +14,7 @@ description: Security best practices for Python library development — secrets,
|
|
|
14
14
|
## 2. Dependency Security
|
|
15
15
|
|
|
16
16
|
- Specify minimum compatible versions for direct dependencies (e.g., `numpy>=2.2.0`) in `pyproject.toml`.
|
|
17
|
-
- Run `pip
|
|
17
|
+
- Run `pip-audit` regularly and in CI to detect known vulnerabilities.
|
|
18
18
|
- Enable GitHub Dependabot for automated dependency update PRs.
|
|
19
19
|
- Review changelogs and diffs before merging dependency updates.
|
|
20
20
|
|
|
@@ -34,7 +34,6 @@ description: Security best practices for Python library development — secrets,
|
|
|
34
34
|
|
|
35
35
|
- NEVER log secrets, tokens, passwords, or full stack traces containing sensitive data.
|
|
36
36
|
- Sanitize PII (personally identifiable information) before logging.
|
|
37
|
-
- Use the `logging` module with appropriate levels so callers can control verbosity.
|
|
38
37
|
|
|
39
38
|
## 6. Code Review Security Checklist
|
|
40
39
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: bug-report
|
|
3
|
-
description: Standards for writing clear, reproducible bug reports
|
|
3
|
+
description: Standards for writing clear, reproducible bug reports with severity, evidence, and environment details. Use when writing, filing, or reviewing a bug report or GitHub issue.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Bug Report Standards
|
|
@@ -56,8 +56,9 @@ Every bug report MUST include:
|
|
|
56
56
|
## Actual Behavior
|
|
57
57
|
[What actually happens, including the full traceback.]
|
|
58
58
|
|
|
59
|
-
## Traceback / Logs
|
|
60
|
-
[Paste full traceback
|
|
59
|
+
## Traceback / Logs / Screenshots / Other Evidence
|
|
60
|
+
[Paste full traceback, relevant log output, screenshots, or other relevant evidence
|
|
61
|
+
here when available]
|
|
61
62
|
|
|
62
63
|
## Additional Notes
|
|
63
64
|
[Workarounds, frequency, related issues.]
|
|
@@ -17,15 +17,15 @@ Analyze all of a project's documentation and produce a **report only** — do no
|
|
|
17
17
|
|
|
18
18
|
## Project rules
|
|
19
19
|
|
|
20
|
-
If the repo contains a `.claude
|
|
20
|
+
If the repo contains a `.claude/` directory, treat these documentation standards as authoritative and cite them by name in findings. `doc_python` is a rule in `.claude/rules/` (always loaded); the others are skills in `.claude/skills/` (read each `SKILL.md` directly):
|
|
21
21
|
|
|
22
|
-
- `doc_python.md` — the **foundation**: documentation system, prose conventions, Sphinx `conf.py` essentials, docstrings, cross-reference completeness, and the build discipline (`-W` warnings-as-errors **and** `-n` nitpicky). Every other doc rule builds on it.
|
|
23
|
-
- `
|
|
24
|
-
- `
|
|
25
|
-
- `
|
|
26
|
-
- `
|
|
22
|
+
- `doc_python` (`.claude/rules/doc_python.md`) — the **foundation**: documentation system, prose conventions, Sphinx `conf.py` essentials, docstrings, cross-reference completeness, and the build discipline (`-W` warnings-as-errors **and** `-n` nitpicky). Every other doc rule builds on it.
|
|
23
|
+
- `doc-readme` (`.claude/skills/doc-readme/SKILL.md`) — the top-level README: badges, the docs-inclusion marker, required sections, quickstart, and links.
|
|
24
|
+
- `doc-user-guide` (`.claude/skills/doc-user-guide/SKILL.md`) — the end-user manual: file layout, landing page + `toctree`, required content, configuration, and per-command-line-program references.
|
|
25
|
+
- `doc-dev-guide` (`.claude/skills/doc-dev-guide/SKILL.md`) — the developer/contributor manual: layout, required chapters, class diagrams, per-module prose, extension recipes, and the API reference.
|
|
26
|
+
- `doc-how-to` (`.claude/skills/doc-how-to/SKILL.md`) — task-focused how-to articles: structure, prerequisites, numbered steps, expected results, and troubleshooting.
|
|
27
27
|
|
|
28
|
-
Not every project ships every rule. **If a referenced rule file does not exist, ignore the corresponding part of the critique** instead of inventing a standard, and do not report the rule's absence as a finding. For example, if there is no `
|
|
28
|
+
Not every project ships every rule. **If a referenced rule file does not exist, ignore the corresponding part of the critique** instead of inventing a standard, and do not report the rule's absence as a finding. For example, if there is no `doc-how-to` skill, skip the how-to checks; if there is no `doc-dev-guide` skill, skip the developer-guide checks. Critique only against the doc rules that are actually present.
|
|
29
29
|
|
|
30
30
|
## Checklist for Analysis
|
|
31
31
|
|
|
@@ -38,7 +38,7 @@ Apply these criteria to the documentation set. Map each finding to the rule file
|
|
|
38
38
|
- **Build cleanliness:** The docs build clean under BOTH `sphinx-build -W` (warnings-as-errors) and `sphinx-build -n` (nitpicky). Note any warnings, broken `toctree` entries, documents not in any `toctree`, or unresolved cross-references. Note `nitpick_ignore` entries that suppress symbols the project actually owns.
|
|
39
39
|
- **Prose conventions:** American spelling; one space after sentence-ending periods; terms defined on first use; **no time-anchored or migration framing** ("new", "legacy", "now", "recently", "backwards compatible"). No unicode smart quotes/em-dashes/arrows inside `.py` files.
|
|
40
40
|
|
|
41
|
-
### 2. Docstrings and API reference (`doc_python`, `
|
|
41
|
+
### 2. Docstrings and API reference (`doc_python`, `doc-dev-guide`)
|
|
42
42
|
|
|
43
43
|
- **Coverage:** Every module, class, method, and function has a docstring. Note missing or one-line-only docstrings on public objects.
|
|
44
44
|
- **Format:** Google style with `Parameters:` (not `Args:`); `Returns:`/`Raises:` present where applicable; wrapped to the project width; describes observable behavior, not internals.
|
|
@@ -49,19 +49,19 @@ Apply these criteria to the documentation set. Map each finding to the rule file
|
|
|
49
49
|
- **Roles:** Every mention of a code object in narrative prose uses the correct Sphinx role (`:class:`, `:meth:`, `:func:`, `:mod:`, `:attr:`, `:data:`); `:doc:`/`:ref:` link pages and labels. Note bare CamelCase or `module.symbol` text (even in inline literals) used for API symbols.
|
|
50
50
|
- **Resolution:** All cross-references resolve under nitpicky mode. Note stale references to renamed/removed objects or moved pages (e.g. relative `:doc:` targets that broke when a page moved into a subdirectory).
|
|
51
51
|
|
|
52
|
-
### 4. README (`
|
|
52
|
+
### 4. README (`doc-readme`)
|
|
53
53
|
|
|
54
54
|
- **Format/inclusion:** Markdown; includable into Sphinx with a marker so host-only badges are excluded from the rendered docs; a single top-level title.
|
|
55
55
|
- **Required sections (in order):** title, grouped status badges, introduction, features, installation (Python versions, prerequisites, install command), quick start, documentation link + local build, contributing link, license.
|
|
56
56
|
- **Content:** Quickstart examples are runnable as written; every shipped command-line program or primary API is mentioned with a pointer to detailed docs; badge/version/entry-point claims match packaging metadata; all links resolve. The README is a summary and entry point, not a manual.
|
|
57
57
|
|
|
58
|
-
### 5. User guide (`
|
|
58
|
+
### 5. User guide (`doc-user-guide`)
|
|
59
59
|
|
|
60
60
|
- **Layout:** Lives in a dedicated `user_guide/` subdirectory; a landing page holds a short intro and a `toctree`; one chapter per feature or per command-line program; instrument/platform/format specifics in clearly named appendix pages; cross-directory `:doc:` targets are absolute, intra-guide ones relative.
|
|
61
61
|
- **Required content:** introduction/purpose; an overview of the workflow/pipeline; installation and setup (versions, install commands, prerequisites, environment variables, expected input/output layout); the full configuration model with precedence and defaults; API usage where applicable; examples.
|
|
62
62
|
- **Command-line program references:** For each program — name, one-line purpose, basic syntax, EVERY option documented (flag, argument, effect, default, env/config equivalents) grouped by purpose, positional/repeatable/value-set notes, at least one runnable example, and the schema of any structured file it consumes/emits. Note options that drift from the actual argument parser.
|
|
63
63
|
|
|
64
|
-
### 6. Developer guide (`
|
|
64
|
+
### 6. Developer guide (`doc-dev-guide`)
|
|
65
65
|
|
|
66
66
|
- **Layout:** Lives in a dedicated subdirectory; a landing page lists chapters in reading order, ending with the API reference and contribution guide.
|
|
67
67
|
- **Required chapters:** introduction (audience + package overview); annotated repository layout; environment setup (editable install, env vars, running entry points + smoke test, running the test suite with tiers/parallel/single-test, lint/type/format/docs commands and any wrapper, CI/CD, release, contribution workflow); architecture/class hierarchy; per-subsystem chapters; extending the system; coding conventions; API reference.
|
|
@@ -69,12 +69,12 @@ Apply these criteria to the documentation set. Map each finding to the rule file
|
|
|
69
69
|
- **Per-module prose:** Each subsystem chapter gives an overview, per-class/per-file description with contracts (methods subclasses must implement and what they return), concrete implementations of each base, important invariants (thread-safety, shared mutable state, units/conventions), and a pointer to the API reference.
|
|
70
70
|
- **Extending:** A step-by-step recipe per extension point with a minimal code skeleton and registration instructions.
|
|
71
71
|
|
|
72
|
-
### 7. How-to articles (`
|
|
72
|
+
### 7. How-to articles (`doc-how-to`)
|
|
73
73
|
|
|
74
74
|
- **Structure:** Action-oriented title; 1-3 sentence intro; prerequisites; numbered steps (one action each, with the exact snippet/command and the observed result); an expected-results summary consistent with the per-step observations; troubleshooting of common failures; related-material links.
|
|
75
75
|
- **Audience/consistency:** Written for a user unfamiliar with internals; where a how-to and the user guide cover the same workflow, they are consistent and link to each other rather than duplicating detail.
|
|
76
76
|
|
|
77
|
-
### 8. Diagrams and figures (`
|
|
77
|
+
### 8. Diagrams and figures (`doc-how-to`, `doc-dev-guide`)
|
|
78
78
|
|
|
79
79
|
- **Use and rendering:** Diagrams are used where a visual is clearer than prose (workflows, pipelines, architecture), placed inline near the relevant section, render in the docs build (validated in their authoring tool), and have descriptive filenames and alt text.
|
|
80
80
|
|
|
@@ -136,13 +136,13 @@ Produce a single markdown report with the following structure. Do **not** edit a
|
|
|
136
136
|
[Self-contained prompt for an AI to apply the fixes. Include:
|
|
137
137
|
- The report sections as context.
|
|
138
138
|
- **Build gate:** The docs must build clean under BOTH `sphinx-build -W` and `sphinx-build -n` before the work is considered done.
|
|
139
|
-
- Instruction to fix documentation according to the report and the present `.claude/rules/
|
|
139
|
+
- Instruction to fix documentation according to the report and the present documentation standards (`.claude/rules/doc_python.md` and the `.claude/skills/doc-*/SKILL.md` skills), without changing production code behavior.
|
|
140
140
|
- Instruction to update every cross-reference and the README/guides in the same change when a symbol or page is renamed or moved.]
|
|
141
141
|
```
|
|
142
142
|
|
|
143
143
|
## Execution steps
|
|
144
144
|
|
|
145
|
-
1. **Inventory rules:** List
|
|
145
|
+
1. **Inventory rules:** List which of `.claude/rules/doc_python.md` and `.claude/skills/doc-*/SKILL.md` exist. Critique only against those; record which are absent so their checklist areas are skipped.
|
|
146
146
|
2. **Gather docs:** List the README and `docs/` tree (note the `toctree` structure and which pages are user guide vs. developer guide vs. how-to vs. API reference). Read `docs/conf.py`.
|
|
147
147
|
3. **Build:** Run `sphinx-build -W -b html docs <out>` and `sphinx-build -n -b html docs <out>` (or the project's documented build) and capture warnings. If the docs cannot be built in this environment, say so and critique statically.
|
|
148
148
|
4. **Read:** Sample the README, each guide landing page and representative chapters, a how-to, and a cross-section of docstrings. Grep for stale references, bare API symbols in prose, and time-anchored phrasing.
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
---
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
- "docs/**/*.rst"
|
|
5
|
-
- "docs/**/*.md"
|
|
2
|
+
name: doc-dev-guide
|
|
3
|
+
description: Format, layout, and completeness rules for the developer/contributor guide of a Python package, covering repository layout, class diagrams, per-module prose, and the API reference. Use when writing, editing, or reviewing the developer guide or API reference under docs/.
|
|
6
4
|
---
|
|
7
5
|
|
|
8
6
|
# Developer Guide
|
|
@@ -34,17 +32,17 @@ what the code already says.
|
|
|
34
32
|
and a statement of which part is the importable public package versus
|
|
35
33
|
supporting code.
|
|
36
34
|
- **Environment setup** — how to get a working development checkout:
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
35
|
+
- Clone, virtual-environment creation, and an editable install with the dev
|
|
36
|
+
extras (`pip install -e ".[dev]"`).
|
|
37
|
+
- Every environment variable needed to run, test, or build, with defaults.
|
|
38
|
+
- How to run the package's entry points locally, including a smoke test.
|
|
39
|
+
- How to run the test suite: the default invocation, how to include slower
|
|
40
|
+
or integration tiers, parallel/CI-matching flags, running a single
|
|
41
|
+
file/test, and coverage. Note the test layout and any required markers.
|
|
42
|
+
- How to run linters, type checks, formatters, and the docs build, plus any
|
|
43
|
+
one-command wrapper that runs them all.
|
|
44
|
+
- The CI/CD pipeline (what runs on which trigger) and the release process.
|
|
45
|
+
- The contribution workflow, or a pointer to the contribution guide.
|
|
48
46
|
- **Architecture / class hierarchy** — see Section 3.
|
|
49
47
|
- **Per-subsystem chapters** — see Section 4.
|
|
50
48
|
- **Extending the system** — see Section 5.
|
|
@@ -1,14 +1,12 @@
|
|
|
1
1
|
---
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
- "docs/**/*.rst"
|
|
5
|
-
- "docs/**/*.md"
|
|
2
|
+
name: doc-how-to
|
|
3
|
+
description: Format and completeness rules for task-focused how-to articles that walk a user through a single workflow with prerequisites, steps, and troubleshooting. Use when writing, editing, or reviewing a how-to article.
|
|
6
4
|
---
|
|
7
5
|
|
|
8
6
|
# How-To Articles
|
|
9
7
|
|
|
10
8
|
A how-to article walks a reader through ONE concrete task from start to finish.
|
|
11
|
-
It complements the reference material in `
|
|
9
|
+
It complements the reference material in the `doc-user-guide` skill: the user guide
|
|
12
10
|
documents every option exhaustively, while a how-to picks one goal and shows the
|
|
13
11
|
shortest correct path to it. Build on `doc_python` (prose conventions, build
|
|
14
12
|
discipline). Where a how-to and the user guide describe the same workflow, keep
|
|
@@ -41,7 +39,7 @@ them consistent and link between them rather than duplicating detail.
|
|
|
41
39
|
|
|
42
40
|
## 3. Structure
|
|
43
41
|
|
|
44
|
-
|
|
42
|
+
````markdown
|
|
45
43
|
# How To [Action]
|
|
46
44
|
|
|
47
45
|
[1-3 sentence introduction explaining purpose and value.]
|
|
@@ -72,7 +70,7 @@ them consistent and link between them rather than duplicating detail.
|
|
|
72
70
|
## Additional Information
|
|
73
71
|
|
|
74
72
|
[Tips, performance notes, or links to related guides.]
|
|
75
|
-
|
|
73
|
+
````
|
|
76
74
|
|
|
77
75
|
## 4. Converting Technical Content
|
|
78
76
|
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
---
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
- "README.md"
|
|
2
|
+
name: doc-readme
|
|
3
|
+
description: Format and completeness rules for the top-level README of a Python package, including badges, quickstart, and Sphinx inclusion. Use when writing, editing, or reviewing the README.
|
|
5
4
|
---
|
|
6
5
|
|
|
7
6
|
# README
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
---
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
- "docs/**/*.rst"
|
|
5
|
-
- "docs/**/*.md"
|
|
2
|
+
name: doc-user-guide
|
|
3
|
+
description: Format, layout, and completeness rules for the end-user guide of a Python package, covering overview, configuration, and command-line program references. Use when writing, editing, or reviewing the user guide under docs/.
|
|
6
4
|
---
|
|
7
5
|
|
|
8
6
|
# User Guide
|
|
@@ -92,4 +90,4 @@ For EACH command-line program the package installs:
|
|
|
92
90
|
the program's actual argument parser and the packaging metadata. When the code
|
|
93
91
|
changes, update the guide in the same change.
|
|
94
92
|
- For step-by-step task walkthroughs that warrant their own article, follow
|
|
95
|
-
`
|
|
93
|
+
the `doc-how-to` skill and link to it from the relevant chapter.
|
|
@@ -10,7 +10,7 @@ description: Commit message format, branch naming, and the pull request workflow
|
|
|
10
10
|
Write the subject as a plain capitalized sentence in the imperative mood, with no type
|
|
11
11
|
prefix:
|
|
12
12
|
|
|
13
|
-
```
|
|
13
|
+
```text
|
|
14
14
|
Add caching to profile lookup
|
|
15
15
|
|
|
16
16
|
[Optional body — wrap at 72 characters. Explain *what* and *why*, not *how*.
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: pull-request
|
|
3
|
-
description:
|
|
3
|
+
description: PR structure, purpose, implementation details, testing evidence, and review checklist. Use when writing a pull request title or description, or when reviewing a pull request.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Pull Request Standards
|
|
7
7
|
|
|
8
8
|
## Scope of review
|
|
9
9
|
|
|
10
|
-
Treat the PR as a **single unit of change**. The diff to review is the set of all commits on the current branch back to its **immediate root** (the merge-base with the target branch). Consider the net result of those commits together; do **not** comment on differences that exist only between commits within the PR (e.g. "you fixed X in a later commit" or "commit 2 undid part of commit 1"). Review the final state of the branch against the base. Do not explicitly word wrap lines.
|
|
10
|
+
Treat the PR as a **single unit of change**. The diff to review is the set of all commits on the current branch back to its **immediate root** (the merge-base with the target branch). Consider the net result of those commits together; do **not** comment on differences that exist only between commits within the PR (e.g. "you fixed X in a later commit" or "commit 2 undid part of commit 1"). Review the final state of the branch against the base. Do not explicitly word wrap lines; allow GitHub to flow them automatically.
|
|
11
11
|
|
|
12
12
|
## Principles
|
|
13
13
|
|
|
@@ -16,22 +16,20 @@ Treat the PR as a **single unit of change**. The diff to review is the set of al
|
|
|
16
16
|
3. **Scope** — One logical change per PR. Split unrelated changes into separate PRs.
|
|
17
17
|
4. **Testing evidence** — Document automated and manual testing performed.
|
|
18
18
|
5. **Impact assessment** — Note potential effects on the public API, performance, or dependent packages (Potential Impacts section).
|
|
19
|
-
6. **Linked issues** — Reference related GitHub issues using `Closes #NNN` syntax.
|
|
19
|
+
6. **Linked issues** — Reference related GitHub issues using `Closes #NNN` syntax. Each issue must be listed separately like `Closes #NNN. Closes #MMM.`.
|
|
20
20
|
|
|
21
21
|
## Template
|
|
22
22
|
|
|
23
23
|
The PR template is in `.github/pull_request_template.md` and is applied automatically when a new PR is opened. Fill out every section:
|
|
24
24
|
|
|
25
|
-
- **Purpose** — Why the change is needed; link issue with `Closes #NNN
|
|
25
|
+
- **Purpose** — Why the change is needed; link issue with `Closes #NNN. Closes #MMM.`.
|
|
26
26
|
- **Changes / Implementation Details** — What changed and how it was implemented; technical approaches chosen and non-obvious design decisions.
|
|
27
|
-
- **
|
|
28
|
-
- **Testing** — Check boxes for unit tests, integration tests, E2E tests run; describe new tests added and manual verification performed.
|
|
27
|
+
- **Testing** — Describe tests changed and new tests added along with test results.
|
|
29
28
|
- **Potential Impacts** — Public API, backward compatibility, performance, downstream; write "None" if straightforward.
|
|
30
|
-
- **Checklist** — Style, mypy, docs, no debug code, no secrets/credentials, no warnings/errors, performance impact assessed, breaking changes flagged.
|
|
31
29
|
- **Notes** — Optional; delete only if not needed (tricky areas, follow-up work).
|
|
32
30
|
|
|
33
31
|
## Guidance
|
|
34
32
|
|
|
35
33
|
- **Library-specific** — Call out public API changes, deprecations, and migration notes in Potential Impacts.
|
|
36
34
|
- **Required reviewers** — Tag maintainers for changes to core modules.
|
|
37
|
-
- **Brevity vs. completeness** — Short enough that authors fill everything out; detailed enough for a reviewer with no other context.
|
|
35
|
+
- **Brevity vs. completeness** — Short enough that authors fill everything out; detailed enough for a reviewer with no other context. If understanding the context for the change requires substantial knowledge, include a discussion of the motivation for the change and its details that is suitable for a reviewer with limited knowledge of the codebase and the concepts being discussed.
|