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.
Files changed (260) hide show
  1. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/.claude/rules/dependency_management.md +2 -1
  2. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/.claude/rules/doc_python.md +42 -24
  3. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/.claude/rules/environment.md +1 -1
  4. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/.claude/rules/logging.md +1 -0
  5. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/.claude/rules/python.md +30 -21
  6. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/.claude/rules/python_testing.md +9 -7
  7. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/.claude/rules/security.md +1 -2
  8. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/.claude/skills/bug-report/SKILL.md +4 -3
  9. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/.claude/skills/critique-documentation/SKILL.md +15 -15
  10. 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
  11. 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
  12. rms_polymath-2.1.1/.claude/rules/doc_readme.md → rms_polymath-2.3.0/.claude/skills/doc-readme/SKILL.md +2 -3
  13. 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
  14. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/.claude/skills/git-workflow/SKILL.md +1 -1
  15. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/.claude/skills/pull-request/SKILL.md +6 -8
  16. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/.claude/skills/python-codebase-analysis/SKILL.md +10 -10
  17. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/.claude/skills/python-codebase-analysis/reference.md +34 -17
  18. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/.claude/skills/run-all-checks/SKILL.md +46 -23
  19. rms_polymath-2.3.0/.codespell-dictionary.txt +9 -0
  20. rms_polymath-2.3.0/.github/dependabot.yml +11 -0
  21. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/.github/workflows/publish_to_pypi.yml +2 -2
  22. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/.github/workflows/publish_to_test_pypi.yml +2 -2
  23. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/.github/workflows/run-tests.yml +18 -10
  24. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/.readthedocs.yaml +2 -0
  25. rms_polymath-2.3.0/.vscode/settings.json +9 -0
  26. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/CLAUDE.md +16 -12
  27. rms_polymath-2.3.0/CONTRIBUTING.md +140 -0
  28. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/PKG-INFO +8 -3
  29. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/README.md +3 -0
  30. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/critiques/2026-08-09-code-critique.md +1 -1
  31. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/docs/conf.py +3 -3
  32. rms_polymath-2.3.0/docs/contributing.rst +13 -0
  33. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/docs/dev_guide/dev_guide_environment.rst +31 -18
  34. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/docs/dev_guide/dev_guide_extensions.rst +2 -2
  35. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/docs/dev_guide/dev_guide_layout.rst +5 -1
  36. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/docs/index.rst +1 -1
  37. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/docs/make.bat +35 -35
  38. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/pyproject.toml +39 -14
  39. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/scripts/read-docs.sh +5 -5
  40. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/scripts/run-all-checks.sh +117 -38
  41. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/src/polymath/_version.py +3 -3
  42. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/src/polymath/boolean.py +1 -1
  43. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/src/polymath/extensions/deriv_ops.py +2 -2
  44. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/src/polymath/extensions/indexer.py +1 -1
  45. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/src/polymath/extensions/math_ops.py +16 -10
  46. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/src/polymath/extensions/readonly_ops.py +6 -6
  47. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/src/polymath/extensions/unit_ops.py +1 -1
  48. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/src/polymath/extensions/vector_ops.py +30 -15
  49. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/src/polymath/matrix.py +1 -1
  50. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/src/polymath/matrix3.py +2 -2
  51. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/src/polymath/polynomial.py +2 -2
  52. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/src/polymath/quaternion.py +1 -1
  53. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/src/polymath/scalar.py +27 -13
  54. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/src/rms_polymath.egg-info/PKG-INFO +8 -3
  55. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/src/rms_polymath.egg-info/SOURCES.txt +9 -8
  56. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/src/rms_polymath.egg-info/requires.txt +1 -0
  57. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/src/rms_polymath.egg-info/scm_file_list.json +9 -8
  58. rms_polymath-2.3.0/src/rms_polymath.egg-info/scm_version.json +8 -0
  59. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_matrix3.py +25 -14
  60. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_matrix3_euler.py +1 -1
  61. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_matrix_comprehensive.py +2 -2
  62. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_pair.py +24 -21
  63. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_polynomial_arithmetic.py +6 -6
  64. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_polynomial_basic.py +14 -8
  65. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_polynomial_operations.py +62 -45
  66. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_qube_coverage.py +6 -6
  67. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_qube_ext_item_ops.py +18 -12
  68. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_qube_ext_mask_ops.py +6 -6
  69. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_qube_ext_math_ops.py +14 -14
  70. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_qube_ext_pickler.py +43 -51
  71. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_qube_ext_shrinker.py +49 -129
  72. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_qube_ext_tvl.py +19 -15
  73. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_qube_ext_vector_ops.py +41 -78
  74. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_qube_identity.py +1 -1
  75. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_qube_new_from_parts.py +1 -1
  76. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_qube_reshaping.py +13 -9
  77. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_qube_unit.py +28 -28
  78. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_scalar_comprehensive.py +8 -4
  79. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_scalar_coverage.py +12 -7
  80. rms_polymath-2.3.0/tests/test_scalar_empty_reductions.py +144 -0
  81. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_units.py +14 -7
  82. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_vector3_basic.py +35 -30
  83. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_vector_comprehensive.py +4 -2
  84. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_vector_reciprocal.py +8 -2
  85. rms_polymath-2.1.1/.claude/rules/documentation.md +0 -64
  86. rms_polymath-2.1.1/.claude/rules/how_to.md +0 -76
  87. rms_polymath-2.1.1/.github/workflows/audit.yml +0 -42
  88. rms_polymath-2.1.1/CONTRIBUTING.md +0 -108
  89. rms_polymath-2.1.1/docs/contributing.rst +0 -8
  90. rms_polymath-2.1.1/src/rms_polymath.egg-info/scm_version.json +0 -8
  91. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/.claude/rules/filecache.md +0 -0
  92. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/.claude/skills/critique-test-suite/SKILL.md +0 -0
  93. {rms_polymath-2.1.1/.vscode → rms_polymath-2.3.0/.cursor}/settings.json +0 -0
  94. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/.flake8 +0 -0
  95. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  96. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/.github/ISSUE_TEMPLATE/config.yml +0 -0
  97. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
  98. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/.github/ISSUE_TEMPLATE/other.md +0 -0
  99. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/.github/pull_request_template.md +0 -0
  100. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/.gitignore +0 -0
  101. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/.stubtest-allowlist +0 -0
  102. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/CODE_OF_CONDUCT.md +0 -0
  103. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/LICENSE +0 -0
  104. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/codecov.yml +0 -0
  105. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/critiques/2026-08-10-performance-critique.md +0 -0
  106. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/docs/Makefile +0 -0
  107. /rms_polymath-2.1.1/docs/CODE_OF_CONDUCT.md → /rms_polymath-2.3.0/docs/code_of_conduct.md +0 -0
  108. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/docs/dev_guide/dev_guide.rst +0 -0
  109. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/docs/dev_guide/dev_guide_architecture.rst +0 -0
  110. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/docs/dev_guide/dev_guide_conventions.rst +0 -0
  111. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/docs/dev_guide/dev_guide_extending.rst +0 -0
  112. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/docs/dev_guide/dev_guide_internal_api.rst +0 -0
  113. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/docs/dev_guide/dev_guide_introduction.rst +0 -0
  114. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/docs/dev_guide/dev_guide_subclasses.rst +0 -0
  115. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/docs/dev_guide/dev_guide_typing.rst +0 -0
  116. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/docs/module.rst +0 -0
  117. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/docs/user_guide/user_guide.rst +0 -0
  118. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/docs/user_guide/user_guide_derivatives.rst +0 -0
  119. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/docs/user_guide/user_guide_indexing.rst +0 -0
  120. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/docs/user_guide/user_guide_introduction.rst +0 -0
  121. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/docs/user_guide/user_guide_masks.rst +0 -0
  122. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/docs/user_guide/user_guide_math.rst +0 -0
  123. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/docs/user_guide/user_guide_objects.rst +0 -0
  124. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/docs/user_guide/user_guide_pickling.rst +0 -0
  125. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/docs/user_guide/user_guide_typing.rst +0 -0
  126. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/docs/user_guide/user_guide_units.rst +0 -0
  127. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/icons/link.png +0 -0
  128. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/requirements.txt +0 -0
  129. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/scripts/setup-venv.sh +0 -0
  130. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/setup.cfg +0 -0
  131. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/src/polymath/__init__.py +0 -0
  132. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/src/polymath/__init__.pyi +0 -0
  133. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/src/polymath/extensions/__init__.py +0 -0
  134. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/src/polymath/extensions/attr_ops.py +0 -0
  135. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/src/polymath/extensions/broadcaster.py +0 -0
  136. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/src/polymath/extensions/casting.py +0 -0
  137. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/src/polymath/extensions/dtypes.py +0 -0
  138. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/src/polymath/extensions/errors.py +0 -0
  139. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/src/polymath/extensions/item_ops.py +0 -0
  140. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/src/polymath/extensions/iterator.py +0 -0
  141. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/src/polymath/extensions/mask_ops.py +0 -0
  142. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/src/polymath/extensions/masking.py +0 -0
  143. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/src/polymath/extensions/pickler.py +0 -0
  144. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/src/polymath/extensions/shaper.py +0 -0
  145. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/src/polymath/extensions/shrinker.py +0 -0
  146. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/src/polymath/extensions/tvl.py +0 -0
  147. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/src/polymath/pair.py +0 -0
  148. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/src/polymath/py.typed +0 -0
  149. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/src/polymath/qube.py +0 -0
  150. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/src/polymath/typedefs.py +0 -0
  151. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/src/polymath/typedefs.pyi +0 -0
  152. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/src/polymath/unit.py +0 -0
  153. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/src/polymath/vector.py +0 -0
  154. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/src/polymath/vector3.py +0 -0
  155. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/src/rms_polymath.egg-info/dependency_links.txt +0 -0
  156. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/src/rms_polymath.egg-info/top_level.txt +0 -0
  157. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/__init__.py +0 -0
  158. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_boolean.py +0 -0
  159. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_indices.py +0 -0
  160. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_math_ops_coverage.py +0 -0
  161. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_matrix3_as_matrix3_validation.py +0 -0
  162. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_matrix3_deriv_class.py +0 -0
  163. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_matrix3_mask_non_unitary.py +0 -0
  164. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_matrix3_pickle.py +0 -0
  165. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_matrix3_precision.py +0 -0
  166. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_matrix3_quaternion.py +0 -0
  167. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_matrix3_to_unitary.py +0 -0
  168. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_matrix3_twovec.py +0 -0
  169. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_matrix_column_vectors.py +0 -0
  170. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_matrix_inverse.py +0 -0
  171. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_matrix_is_diagonal.py +0 -0
  172. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_matrix_misc.py +0 -0
  173. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_matrix_ops.py +0 -0
  174. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_matrix_row_vectors.py +0 -0
  175. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_matrix_solve.py +0 -0
  176. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_pair_as_pair.py +0 -0
  177. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_pair_clip2d.py +0 -0
  178. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_pair_misc.py +0 -0
  179. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_pair_swapxy.py +0 -0
  180. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_quaternion.py +0 -0
  181. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_quaternion_euler.py +0 -0
  182. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_quaternion_matrix3.py +0 -0
  183. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_quaternion_ops.py +0 -0
  184. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_quaternion_parts.py +0 -0
  185. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_qube_add_attr.py +0 -0
  186. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_qube_all.py +0 -0
  187. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_qube_any.py +0 -0
  188. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_qube_as_this_type.py +0 -0
  189. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_qube_cast.py +0 -0
  190. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_qube_clone.py +0 -0
  191. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_qube_derivs.py +0 -0
  192. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_qube_errstate_independence.py +0 -0
  193. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_qube_getitem.py +0 -0
  194. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_qube_getstate.py +0 -0
  195. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_qube_items.py +0 -0
  196. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_qube_iterate.py +0 -0
  197. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_qube_mask_nans_infs.py +0 -0
  198. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_qube_masking.py +0 -0
  199. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_qube_power.py +0 -0
  200. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_qube_readonly.py +0 -0
  201. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_qube_setitem.py +0 -0
  202. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_qube_shrink.py +0 -0
  203. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_qube_stack.py +0 -0
  204. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_qube_types.py +0 -0
  205. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_qube_zero.py +0 -0
  206. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_scalar_arccos.py +0 -0
  207. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_scalar_arcsin.py +0 -0
  208. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_scalar_arctan.py +0 -0
  209. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_scalar_arctan2.py +0 -0
  210. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_scalar_as_index.py +0 -0
  211. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_scalar_as_scalar.py +0 -0
  212. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_scalar_cos.py +0 -0
  213. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_scalar_exp.py +0 -0
  214. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_scalar_frac.py +0 -0
  215. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_scalar_int.py +0 -0
  216. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_scalar_log.py +0 -0
  217. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_scalar_max.py +0 -0
  218. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_scalar_maximum.py +0 -0
  219. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_scalar_mean.py +0 -0
  220. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_scalar_median.py +0 -0
  221. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_scalar_min.py +0 -0
  222. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_scalar_minimum.py +0 -0
  223. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_scalar_misc.py +0 -0
  224. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_scalar_ops.py +0 -0
  225. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_scalar_quadratic.py +0 -0
  226. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_scalar_sign.py +0 -0
  227. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_scalar_sin.py +0 -0
  228. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_scalar_sqrt.py +0 -0
  229. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_scalar_sum.py +0 -0
  230. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_scalar_tan.py +0 -0
  231. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_typedefs.py +0 -0
  232. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_vector3_advanced.py +0 -0
  233. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_vector3_misc.py +0 -0
  234. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_vector3_operations.py +0 -0
  235. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_vector3_spin.py +0 -0
  236. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_vector_as_column.py +0 -0
  237. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_vector_as_diagonal.py +0 -0
  238. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_vector_as_index.py +0 -0
  239. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_vector_as_row.py +0 -0
  240. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_vector_as_vector.py +0 -0
  241. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_vector_cross_2x2.py +0 -0
  242. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_vector_cross_3x3.py +0 -0
  243. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_vector_dot.py +0 -0
  244. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_vector_element_div.py +0 -0
  245. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_vector_element_mul.py +0 -0
  246. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_vector_int.py +0 -0
  247. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_vector_masking.py +0 -0
  248. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_vector_mean_sum.py +0 -0
  249. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_vector_norm.py +0 -0
  250. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_vector_norm_sq.py +0 -0
  251. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_vector_ops.py +0 -0
  252. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_vector_outer.py +0 -0
  253. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_vector_perp.py +0 -0
  254. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_vector_proj.py +0 -0
  255. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_vector_scalars.py +0 -0
  256. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_vector_sep.py +0 -0
  257. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_vector_to_pair.py +0 -0
  258. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_vector_ucross.py +0 -0
  259. {rms_polymath-2.1.1 → rms_polymath-2.3.0}/tests/test_vector_unit.py +0 -0
  260. {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 audit` in CI to catch known vulnerabilities.
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 rules.
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 rules build on it:
9
+ Python package. The companion skills (in `.claude/skills/`, loaded when a task
10
+ calls for them) build on it:
10
11
 
11
- - `doc_readme` — the top-level `README`.
12
- - `doc_user_guide` — the end-user manual.
13
- - `doc_dev_guide` — the contributor / maintainer manual and API reference.
14
- - `doc_how_to` — task-focused how-to articles.
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 (e.g. `color`, not `colour`).
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
- - `sphinx.ext.autodoc` — pull API docs from docstrings.
51
- - `sphinx.ext.napoleon` — parse Google-style docstrings.
52
- - `sphinx.ext.viewcode` — link API docs to highlighted source.
53
- - `sphinx.ext.intersphinx` — cross-link to the docs of Python and key
54
- third-party dependencies; populate `intersphinx_mapping` accordingly.
55
- - `myst_parser` — include Markdown files (the `README`).
56
- - A diagram extension (e.g. `sphinxcontrib.mermaid`) when the guides use
57
- diagrams; configure it for headless/client-side rendering so CI needs no
58
- browser.
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
- - `:class:`~package.module.Class``
89
- - `:meth:`~package.module.Class.method``
90
- - `:func:`~package.module.func``
91
- - `:mod:`package.module``
92
- - `:attr:`~package.module.Class.attr``
93
- - `:data:`~package.module.NAME``
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 (`` `` ``) are for YAML/JSON
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 `doc_dev_guide`).
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
- - Always match the coding style of pre-existing Python files.
22
- - Always make the minimal changes necessary. Never modify code outside the scope of the current task.
23
- - Do not include backwards-compatibility code unless explicitly requested.
24
- - Always write simple, clear code; avoid unnecessary complexity.
25
- - Define magic constants as module-level constants, in a config module, or via environment variables.
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, always provide full exception information for debugging (e.g. traceback, `raise ... from` when re-raising).
29
- - Include meaningful, structured logging (use the `logging` module) that can be disabled or redirected. Never use bare `print()` for diagnostic output in library code.
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
- - Always prefer comprehensions (list, dict, set, generator) over manual loops when the result is a new collection and the expression remains readable.
32
- - Apply DRY. Avoid duplicating code. Place reusable logic in a utility module. Search existing utilities before writing new functions. Parameterize utility functions to increase generality.
33
- - 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).
34
- - Limit new functions to at most 5 positional parameters. Additional parameters should be keyword-only (after `*`). Choose a logical grouping of 0-5 positional parameters before enforcing keyword-only parameters.
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
- - Never use `getattr` just as a defensive measure if it is guaranteed that the object has the attribute. 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.
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 include comments that merely restate the code, reference user requests, or describe modification history.
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
- - Annotate all test function/method parameters and return values, including `-> None` for functions (and `__init__`) that return nothing.
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
- - Run `mypy` on the tests after changes. Fix all errors before delivering.
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
- - Include `mypy` and `ruff` in the project's dev dependencies (e.g. in `pyproject.toml`).
69
- - Run `ruff check` on the full codebase after changes
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
- - Include a docstring for every module, class, function, and method.
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 and `pytest-xdist` for parallelism; run
28
- with `-n auto`. Declare all three in the dev dependency group.
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
- - `tmp_path` / `tmp_path_factory` for filesystem work — never write into the
73
- repo or a fixed temp path.
74
- - `monkeypatch` for environment variables, attributes, and `sys` state — it
75
- auto-reverts after the test.
76
- - `capsys` (or `capfd`) to capture and assert on stdout/stderr.
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 audit` regularly and in CI to detect known vulnerabilities.
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, covering required components, severity levels, evidence, and environment details. Use when the user asks to write, file, or review a bug report or issue.
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 or relevant log output here]
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/rules/` directory, treat these documentation rule files as the authoritative standard and cite them by filename in findings:
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
- - `doc_readme.md` — the top-level README: badges, the docs-inclusion marker, required sections, quickstart, and links.
24
- - `doc_user_guide.md` — the end-user manual: file layout, landing page + `toctree`, required content, configuration, and per-command-line-program references.
25
- - `doc_dev_guide.md` — the developer/contributor manual: layout, required chapters, class diagrams, per-module prose, extension recipes, and the API reference.
26
- - `doc_how_to.md` — task-focused how-to articles: structure, prerequisites, numbered steps, expected results, and troubleshooting.
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 `doc_how_to.md`, skip the how-to checks; if there is no `doc_dev_guide.md`, skip the developer-guide checks. Critique only against the doc rules that are actually present.
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`, `doc_dev_guide`)
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 (`doc_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 (`doc_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 (`doc_dev_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 (`doc_how_to`)
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 (`doc_how_to`, `doc_dev_guide`)
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/doc_*.md` rules, without changing production code behavior.
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 the `.claude/rules/doc_*.md` files that exist. Critique only against those; record which are absent so their checklist areas are skipped.
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
- 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.
3
- paths:
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
- - Clone, virtual-environment creation, and an editable install with the dev
38
- extras (`pip install -e ".[dev]"`).
39
- - Every environment variable needed to run, test, or build, with defaults.
40
- - How to run the package's entry points locally, including a smoke test.
41
- - How to run the test suite: the default invocation, how to include slower
42
- or integration tiers, parallel/CI-matching flags, running a single
43
- file/test, and coverage. Note the test layout and any required markers.
44
- - How to run linters, type checks, formatters, and the docs build, plus any
45
- one-command wrapper that runs them all.
46
- - The CI/CD pipeline (what runs on which trigger) and the release process.
47
- - The contribution workflow, or a pointer to the contribution guide.
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
- description: Format and completeness rules for task-focused how-to articles that walk a user through a single workflow with prerequisites, steps, and troubleshooting.
3
- paths:
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 `doc_user_guide`: the user guide
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
- ```markdown
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
- description: Format and completeness rules for the top-level README of a Python package, including badges, quickstart, and Sphinx inclusion.
3
- paths:
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
- description: Format, layout, and completeness rules for the end-user guide of a Python package, covering overview, configuration, and command-line program references.
3
- paths:
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
- `doc_how_to` and link to it from the relevant chapter.
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: Standards for pull request structure, covering purpose, implementation details, testing evidence, and the review checklist. Use when the user asks to write a pull request description, open a PR, or review one.
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
- - **Type of Change** — Check all that apply (bug fix, feature, breaking, refactor, docs, tests, CI/build).
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.