code-standards 8.132.2__tar.gz → 8.132.4__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 (205) hide show
  1. {code_standards-8.132.2 → code_standards-8.132.4}/PKG-INFO +3 -3
  2. {code_standards-8.132.2 → code_standards-8.132.4}/README.md +1 -1
  3. {code_standards-8.132.2 → code_standards-8.132.4}/pyproject.toml +2 -2
  4. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/api.py +21 -12
  5. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/configs/cli-reference.v1.json +2 -2
  6. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/configs/eslint.peers.json +2 -3
  7. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/configs/eslint.strict.mjs +0 -2
  8. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/configs/eslint.strict.ts +0 -2
  9. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/configs/ruff.strict.toml +0 -1
  10. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/libs/linting/library_policy.py +95 -7
  11. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/libs/linting/runner.py +2 -1
  12. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/libs/repository/docs.py +3 -3
  13. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/libs/repository/hooks.py +1 -1
  14. code_standards-8.132.4/src/sarj_standards/schemas/rule-catalog.v1.json +1 -0
  15. code_standards-8.132.2/src/sarj_standards/schemas/rule-catalog.v1.json +0 -1
  16. {code_standards-8.132.2 → code_standards-8.132.4}/.gitignore +0 -0
  17. {code_standards-8.132.2 → code_standards-8.132.4}/LICENSE +0 -0
  18. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/__init__.py +0 -0
  19. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/__main__.py +0 -0
  20. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/_meta.py +0 -0
  21. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/cli/__init__.py +0 -0
  22. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/cli/main.py +0 -0
  23. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/configs/Mintfile.mobile.strict +0 -0
  24. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/configs/action-parser/LICENSE.actions +0 -0
  25. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/configs/action-parser/LICENSE.cronstrue +0 -0
  26. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/configs/action-parser/LICENSE.yaml +0 -0
  27. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/configs/action-parser/generate.mts +0 -0
  28. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/configs/action-parser/index.mts +0 -0
  29. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/configs/action-parser/package-lock.json +0 -0
  30. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/configs/action-parser/package.json +0 -0
  31. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/configs/action-parser/upstream.json +0 -0
  32. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/configs/action-parser.cjs +0 -0
  33. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/configs/actionlint.strict.yaml +0 -0
  34. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/configs/basedpyright.python315-watch.json +0 -0
  35. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/configs/basedpyright.strict.json +0 -0
  36. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/configs/checkov.strict.yml +0 -0
  37. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/configs/compile-eslint.mts +0 -0
  38. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/configs/detekt.strict.yml +0 -0
  39. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/configs/devops-verification.v1.json +0 -0
  40. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/configs/doctor.config.json +0 -0
  41. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/configs/eslint-compact-formatter.mts +0 -0
  42. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/configs/eslint-required-policy.mts +0 -0
  43. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/configs/eslint-selected-rules.mts +0 -0
  44. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/configs/eslint.application.mjs +0 -0
  45. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/configs/hadolint.strict.yaml +0 -0
  46. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/configs/ktlint.strict.editorconfig +0 -0
  47. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/configs/markdownlint.strict.yaml +0 -0
  48. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/configs/mobile-tools.versions.json +0 -0
  49. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/configs/mobsf.strict.yml +0 -0
  50. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/configs/pyright.strict.json +0 -0
  51. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/configs/ruff.application.toml +0 -0
  52. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/configs/ruff.cast.toml +0 -0
  53. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/configs/ruff.python315-watch.toml +0 -0
  54. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/configs/ruff.required.toml +0 -0
  55. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/configs/rule-calibration-campaign.v1.json +0 -0
  56. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/configs/rule-inventory.v1.json +0 -0
  57. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/configs/rule-ledger.json +0 -0
  58. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/configs/rule-level-source.mts +0 -0
  59. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/configs/schemas/SKAFFOLD-LICENSE +0 -0
  60. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/configs/schemas/google-build-v1-schema.json +0 -0
  61. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/configs/schemas/google-build-v1.LICENSE +0 -0
  62. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/configs/schemas/skaffold-v4beta7.json +0 -0
  63. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/configs/schemas/upstream-schemas.json +0 -0
  64. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/configs/semgrep-overrides.txt +0 -0
  65. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/configs/shellcheck.strict.rc +0 -0
  66. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/configs/swiftformat.strict +0 -0
  67. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/configs/swiftlint.strict.yml +0 -0
  68. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/configs/taplo.strict.toml +0 -0
  69. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/configs/tflint.strict.hcl +0 -0
  70. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/configs/tflint.version.hcl +0 -0
  71. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/configs/tool-json.mts +0 -0
  72. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/configs/yamllint.strict.yaml +0 -0
  73. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/configs/zizmor.strict.yml +0 -0
  74. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/libs/__init__.py +0 -0
  75. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/libs/adoption/__init__.py +0 -0
  76. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/libs/adoption/age_transition.py +0 -0
  77. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/libs/adoption/configs.py +0 -0
  78. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/libs/adoption/devops.py +0 -0
  79. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/libs/adoption/doctor.py +0 -0
  80. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/libs/adoption/exclusions.py +0 -0
  81. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/libs/adoption/hooks.py +0 -0
  82. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/libs/adoption/launcher.py +0 -0
  83. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/libs/adoption/lifecycle.py +0 -0
  84. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/libs/adoption/manifest.py +0 -0
  85. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/libs/adoption/native_bootstrap.py +0 -0
  86. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/libs/adoption/packagemanager.py +0 -0
  87. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/libs/adoption/repository_baseline.py +0 -0
  88. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/libs/adoption/retired_suppressions.py +0 -0
  89. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/libs/adoption/scaffold.py +0 -0
  90. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/libs/adoption/service.py +0 -0
  91. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/libs/adoption/transaction.py +0 -0
  92. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/libs/adoption/upgrade.py +0 -0
  93. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/libs/adoption/uvtool.py +0 -0
  94. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/libs/catalogs/__init__.py +0 -0
  95. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/libs/catalogs/slack_automations.py +0 -0
  96. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/libs/corpus/__init__.py +0 -0
  97. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/libs/corpus/manifest.py +0 -0
  98. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/libs/corpus/snapshot.py +0 -0
  99. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/libs/diagnostics/__init__.py +0 -0
  100. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/libs/diagnostics/analysis.schema.json +0 -0
  101. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/libs/diagnostics/baseline.py +0 -0
  102. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/libs/diagnostics/models.py +0 -0
  103. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/libs/diagnostics/serialize.py +0 -0
  104. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/libs/diagnostics/source.py +0 -0
  105. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/libs/filesystem.py +0 -0
  106. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/libs/json_boundary.py +0 -0
  107. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/libs/linting/__init__.py +0 -0
  108. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/libs/linting/_cloudbuild_autofix.py +0 -0
  109. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/libs/linting/action_metadata.py +0 -0
  110. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/libs/linting/analysis.py +0 -0
  111. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/libs/linting/autofix.py +0 -0
  112. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/libs/linting/chart_schemas.py +0 -0
  113. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/libs/linting/cloudbuild.py +0 -0
  114. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/libs/linting/cloudbuild_schema.py +0 -0
  115. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/libs/linting/complexity_baseline.py +0 -0
  116. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/libs/linting/devops_programs.py +0 -0
  117. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/libs/linting/devops_schema.py +0 -0
  118. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/libs/linting/devops_source.py +0 -0
  119. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/libs/linting/devops_tools.py +0 -0
  120. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/libs/linting/duplicate_code.py +0 -0
  121. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/libs/linting/embedded_shell.py +0 -0
  122. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/libs/linting/external.py +0 -0
  123. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/libs/linting/kubernetes_context.py +0 -0
  124. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/libs/linting/mobile_tools.py +0 -0
  125. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/libs/linting/policy.py +0 -0
  126. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/libs/linting/prepared_devops.py +0 -0
  127. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/libs/linting/prepared_kubernetes.py +0 -0
  128. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/libs/linting/prepared_native.py +0 -0
  129. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/libs/linting/python_fixes.py +0 -0
  130. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/libs/linting/repo_standards.py +0 -0
  131. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/libs/linting/scheduling.py +0 -0
  132. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/libs/linting/security_tools.py +0 -0
  133. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/libs/linting/shell_ast.py +0 -0
  134. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/libs/linting/shell_format.py +0 -0
  135. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/libs/linting/shell_policy.py +0 -0
  136. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/libs/linting/test_value.py +0 -0
  137. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/libs/linting/text_rule_base.py +0 -0
  138. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/libs/linting/text_rules/__init__.py +0 -0
  139. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/libs/linting/text_rules/_registry.py +0 -0
  140. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/libs/linting/text_rules/cloudbuild_contract.py +0 -0
  141. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/libs/linting/textlint.py +0 -0
  142. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/libs/linting/toml_literals.py +0 -0
  143. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/libs/linting/unused_modules.py +0 -0
  144. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/libs/release/__init__.py +0 -0
  145. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/libs/release/_values.py +0 -0
  146. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/libs/release/artifacts.py +0 -0
  147. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/libs/release/causality.py +0 -0
  148. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/libs/release/changes.py +0 -0
  149. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/libs/release/ci_artifacts.py +0 -0
  150. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/libs/release/make_checks.py +0 -0
  151. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/libs/release/metadata_verification.py +0 -0
  152. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/libs/release/native_test_setup.py +0 -0
  153. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/libs/release/process.py +0 -0
  154. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/libs/release/publish.py +0 -0
  155. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/libs/release/registry.py +0 -0
  156. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/libs/release/release_age.py +0 -0
  157. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/libs/release/release_detect.py +0 -0
  158. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/libs/release/retirement.py +0 -0
  159. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/libs/release/reviewed_analysis.py +0 -0
  160. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/libs/release/rollout.py +0 -0
  161. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/libs/release/status.py +0 -0
  162. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/libs/release/tags.py +0 -0
  163. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/libs/release/test_selection.py +0 -0
  164. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/libs/release/typescript.py +0 -0
  165. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/libs/release/verification_process.py +0 -0
  166. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/libs/release/wheel_tests.py +0 -0
  167. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/libs/repository/__init__.py +0 -0
  168. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/libs/repository/cli_examples.py +0 -0
  169. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/libs/repository/cli_reference_artifact.py +0 -0
  170. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/libs/repository/cloudbuild_schema_projection.py +0 -0
  171. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/libs/repository/comment_corpus.py +0 -0
  172. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/libs/repository/config_generation.py +0 -0
  173. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/libs/repository/immutable_git.py +0 -0
  174. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/libs/repository/ledger.py +0 -0
  175. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/libs/repository/repository.py +0 -0
  176. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/libs/repository/ruff_freshness.py +0 -0
  177. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/libs/repository/rule_authoring.py +0 -0
  178. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/libs/repository/rule_catalog_artifact.py +0 -0
  179. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/libs/repository/rule_changes.py +0 -0
  180. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/libs/repository/rule_checkout.py +0 -0
  181. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/libs/repository/rule_dependencies.py +0 -0
  182. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/libs/repository/rule_examples.py +0 -0
  183. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/libs/repository/rule_imports.mts +0 -0
  184. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/libs/repository/rule_inventory_artifact.py +0 -0
  185. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/libs/repository/rule_level_source.py +0 -0
  186. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/libs/repository/rule_lifecycle.py +0 -0
  187. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/libs/repository/rule_maintenance.py +0 -0
  188. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/libs/repository/rule_registration.py +0 -0
  189. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/libs/repository/shell_checks.py +0 -0
  190. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/libs/repository/third_party_catalog_artifact.py +0 -0
  191. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/libs/rules/__init__.py +0 -0
  192. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/libs/rules/catalog.py +0 -0
  193. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/libs/rules/contracts.py +0 -0
  194. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/libs/rules/corpus_runner.py +0 -0
  195. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/libs/rules/evaluation.py +0 -0
  196. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/libs/schema_boundary.py +0 -0
  197. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/libs/setup/__init__.py +0 -0
  198. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/libs/setup/repository.py +0 -0
  199. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/libs/typed_containers.py +0 -0
  200. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/libs/yaml_boundary.py +0 -0
  201. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/py.typed +0 -0
  202. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/schemas/__init__.py +0 -0
  203. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/schemas/_paths.py +0 -0
  204. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/schemas/rule-catalog.v1.schema.json +0 -0
  205. {code_standards-8.132.2 → code_standards-8.132.4}/src/sarj_standards/schemas/slack-automations.v1.schema.json +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: code-standards
3
- Version: 8.132.2
3
+ Version: 8.132.4
4
4
  Summary: One deterministic quality gate for Sarj Python, TypeScript, Swift, Kotlin, shell, SQL, IaC, and repository policy.
5
5
  Project-URL: Homepage, https://code-standards.sarj.ai/
6
6
  Project-URL: Documentation, https://code-standards.sarj.ai/cli/
@@ -31,7 +31,7 @@ Requires-Dist: referencing==0.37.0
31
31
  Requires-Dist: repo-standards==6.12.9
32
32
  Requires-Dist: ruff==0.17.2
33
33
  Requires-Dist: sarj-iac-lint==0.30.1
34
- Requires-Dist: sarj-python-lint==1.77.2
34
+ Requires-Dist: sarj-python-lint==1.77.3
35
35
  Requires-Dist: sarj-rule-contracts==0.4.1
36
36
  Requires-Dist: sarj-sql-lint==0.26.1
37
37
  Requires-Dist: shellcheck-py==0.11.0.1; (sys_platform == 'darwin' and platform_machine == 'arm64') or (sys_platform == 'darwin' and platform_machine == 'x86_64') or (sys_platform == 'linux' and platform_machine == 'x86_64') or (sys_platform == 'win32' and platform_machine == 'AMD64')
@@ -73,7 +73,7 @@ The complete Python and JavaScript/TypeScript source gate requires named, line-l
73
73
 
74
74
  The complete Standards gate enforces Ruff's ban on `typing.cast` and `typing_extensions.cast` even when source comments, consumer Ruff configuration or manifest rule exceptions suppress `banned-api`; these cast findings cannot enter or consume the diagnostic baseline. Wildcard imports, bounded literal `getattr` names and proven read-only typing module namespace lookups through `__dict__`, `vars` and `__getattribute__` retain the same ban. Other banned APIs retain their existing exception policy. Prefer discriminated unions, explicit narrowing and typed contracts. The warning `python:no-dual-shape-model-field-reader` (SARJ522) identifies private helpers that read the same declared Pydantic fields through model `getattr` and mapping lookup branches, returning `object` or `Any`. Normalize raw input once and read typed attributes. Opaque inputs, raw validators and genuinely dynamic reflection remain supported. Review changes to missing-field handling, coercion, generated defaults and validation errors; there is no autofix.
75
75
 
76
- Python boolean traps are owned by Ruff FBT001, FBT002 and FBT003: positional boolean annotations, defaults and literal arguments are checked; keyword-only inputs, named arguments and the existing test exemptions remain allowed. The typed ESLint policy uses `@sarj/no-boolean-selector-parameter` at warning severity. This adapter retains maintained SonarJS S2301 detection and adds concise-arrow conditional dispatch. Prefer separate intention-revealing operations or an explicit string-literal mode. Boolean data, syntactic value mappings, stable same-operation data choices, setters and independently declared callback or inherited contracts remain allowed. Independent JSX helpers are checked; types and references establish callback contracts. It requires type information and a direct broad-boolean parameter condition. Multi-statement bodies, short-circuit guards, nullable or literal-only inputs and indirect predicates remain outside its scope. The inherited upstream block-body `onX` property exemption remains a documented blind spot. Use `code-standards check --rule eslint:no-boolean-selector-parameter` to inspect it. Noncomputed property reads count as data without proving getter effects; computed reads, including literal keys, remain outside that exemption. API changes require manual review; the rule provides no automatic rewrite.
76
+ Python boolean traps are owned by Ruff FBT001, FBT002 and FBT003: positional boolean annotations, defaults and literal arguments are checked; keyword-only inputs, named arguments and the existing test exemptions remain allowed. The typed ESLint policy uses `@sarj/no-boolean-selector-parameter` at warning severity. Its owned detector checks single-statement operation selectors and concise-arrow conditional dispatch. Prefer separate intention-revealing operations or an explicit string-literal mode. Boolean data, syntactic value mappings, stable same-operation data choices, setters and independently declared callback or inherited contracts remain allowed. Independent JSX helpers are checked; types and references establish callback contracts. It requires type information and a direct broad-boolean parameter condition. Multi-statement bodies, short-circuit guards, nullable or literal-only inputs and indirect predicates remain outside its scope. The preserved block-body `onX` property exemption remains a documented blind spot. Use `code-standards check --rule eslint:no-boolean-selector-parameter` to inspect it. Noncomputed property reads count as data without proving getter effects; computed reads, including literal keys, remain outside that exemption. API changes require manual review; the rule provides no automatic rewrite.
77
77
 
78
78
  The shared ESLint policy also warns on unparenthesized assignments in returned expressions through native `no-return-assign`. Review whether the assignment should be a comparison or a separate state change; there is no automatic intent-changing fix. The native `except-parens` option accepts individually grouped assignments and common lazy memoization. Parentheses mark syntactic visibility, not proven intent: formatters can add or remove them without changing behavior. A chained assignment can still warn after formatting even when its outer expression is grouped. For an intentional local-variable chain, use separate assignment statements followed by return. Upstream may report several writes at the same return location. This rule does not prohibit all returned mutations or prove command/query separation. Existing typed void-return and Promise checks retain their own boundaries; an executor's returned expression alone does not prove a broken Promise.
79
79
 
@@ -33,7 +33,7 @@ The complete Python and JavaScript/TypeScript source gate requires named, line-l
33
33
 
34
34
  The complete Standards gate enforces Ruff's ban on `typing.cast` and `typing_extensions.cast` even when source comments, consumer Ruff configuration or manifest rule exceptions suppress `banned-api`; these cast findings cannot enter or consume the diagnostic baseline. Wildcard imports, bounded literal `getattr` names and proven read-only typing module namespace lookups through `__dict__`, `vars` and `__getattribute__` retain the same ban. Other banned APIs retain their existing exception policy. Prefer discriminated unions, explicit narrowing and typed contracts. The warning `python:no-dual-shape-model-field-reader` (SARJ522) identifies private helpers that read the same declared Pydantic fields through model `getattr` and mapping lookup branches, returning `object` or `Any`. Normalize raw input once and read typed attributes. Opaque inputs, raw validators and genuinely dynamic reflection remain supported. Review changes to missing-field handling, coercion, generated defaults and validation errors; there is no autofix.
35
35
 
36
- Python boolean traps are owned by Ruff FBT001, FBT002 and FBT003: positional boolean annotations, defaults and literal arguments are checked; keyword-only inputs, named arguments and the existing test exemptions remain allowed. The typed ESLint policy uses `@sarj/no-boolean-selector-parameter` at warning severity. This adapter retains maintained SonarJS S2301 detection and adds concise-arrow conditional dispatch. Prefer separate intention-revealing operations or an explicit string-literal mode. Boolean data, syntactic value mappings, stable same-operation data choices, setters and independently declared callback or inherited contracts remain allowed. Independent JSX helpers are checked; types and references establish callback contracts. It requires type information and a direct broad-boolean parameter condition. Multi-statement bodies, short-circuit guards, nullable or literal-only inputs and indirect predicates remain outside its scope. The inherited upstream block-body `onX` property exemption remains a documented blind spot. Use `code-standards check --rule eslint:no-boolean-selector-parameter` to inspect it. Noncomputed property reads count as data without proving getter effects; computed reads, including literal keys, remain outside that exemption. API changes require manual review; the rule provides no automatic rewrite.
36
+ Python boolean traps are owned by Ruff FBT001, FBT002 and FBT003: positional boolean annotations, defaults and literal arguments are checked; keyword-only inputs, named arguments and the existing test exemptions remain allowed. The typed ESLint policy uses `@sarj/no-boolean-selector-parameter` at warning severity. Its owned detector checks single-statement operation selectors and concise-arrow conditional dispatch. Prefer separate intention-revealing operations or an explicit string-literal mode. Boolean data, syntactic value mappings, stable same-operation data choices, setters and independently declared callback or inherited contracts remain allowed. Independent JSX helpers are checked; types and references establish callback contracts. It requires type information and a direct broad-boolean parameter condition. Multi-statement bodies, short-circuit guards, nullable or literal-only inputs and indirect predicates remain outside its scope. The preserved block-body `onX` property exemption remains a documented blind spot. Use `code-standards check --rule eslint:no-boolean-selector-parameter` to inspect it. Noncomputed property reads count as data without proving getter effects; computed reads, including literal keys, remain outside that exemption. API changes require manual review; the rule provides no automatic rewrite.
37
37
 
38
38
  The shared ESLint policy also warns on unparenthesized assignments in returned expressions through native `no-return-assign`. Review whether the assignment should be a comparison or a separate state change; there is no automatic intent-changing fix. The native `except-parens` option accepts individually grouped assignments and common lazy memoization. Parentheses mark syntactic visibility, not proven intent: formatters can add or remove them without changing behavior. A chained assignment can still warn after formatting even when its outer expression is grouped. For an intentional local-variable chain, use separate assignment statements followed by return. Upstream may report several writes at the same return location. This rule does not prohibit all returned mutations or prove command/query separation. Existing typed void-return and Promise checks retain their own boundaries; an executor's returned expression alone does not prove a broken Promise.
39
39
 
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "code-standards"
3
- version = "8.132.2"
3
+ version = "8.132.4"
4
4
  description = "One deterministic quality gate for Sarj Python, TypeScript, Swift, Kotlin, shell, SQL, IaC, and repository policy."
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.14"
@@ -32,7 +32,7 @@ dependencies = [
32
32
  "ruff==0.17.2",
33
33
  "shellcheck-py==0.11.0.1; (sys_platform == 'darwin' and platform_machine == 'arm64') or (sys_platform == 'darwin' and platform_machine == 'x86_64') or (sys_platform == 'linux' and platform_machine == 'x86_64') or (sys_platform == 'win32' and platform_machine == 'AMD64')",
34
34
  "sarj-iac-lint==0.30.1",
35
- "sarj-python-lint==1.77.2",
35
+ "sarj-python-lint==1.77.3",
36
36
  "sarj-sql-lint==0.26.1",
37
37
  "typer==0.27.3",
38
38
  ]
@@ -228,7 +228,10 @@ class Standards:
228
228
  exit_code=_INVALID_EXIT,
229
229
  )
230
230
  try:
231
- policy_findings = check_selected_library_policy(self.root, selected)
231
+ selected_groups = group_paths(selected, policy=policy)
232
+ policy_findings = check_selected_library_policy(
233
+ self.root, selected, python_paths=selected_groups.python
234
+ )
232
235
  except (OSError, TypeError, ValueError, ManifestPolicyError) as exc:
233
236
  return Result(
234
237
  Status.INVALID,
@@ -239,7 +242,7 @@ class Standards:
239
242
  Finding(item.id, "error", item.message, str(item.path), f"use {item.replacement}")
240
243
  for item in policy_findings
241
244
  )
242
- source_status = check(selected, policy=policy)
245
+ source_status = check(selected, policy=policy, grouped=selected_groups)
243
246
  eslint_status = execute(selected_eslint_commands(self.root, selected))
244
247
  return _operation_result(max(source_status, eslint_status, 1 if findings else 0), findings=findings)
245
248
  return _operation_result(_verify(self.root))
@@ -306,7 +309,9 @@ class Standards:
306
309
  rule_selection=rule_selection,
307
310
  )
308
311
  if rule_selection is None:
309
- native = _with_library_policy(self.root, native, active_selected, selection_policy)
312
+ native = _with_library_policy(
313
+ self.root, native, active_selected, selection_policy, python_paths=selected_groups.python
314
+ )
310
315
  if rule_selection is None and normalized_mode is AnalysisMode.POLICY:
311
316
  native = _with_repository_analysis(self.root, native, staged=staged)
312
317
  prepared = _prepared_reports(self.root, adopted, prepared_devops, prepared_targets, trust=normalized_trust)
@@ -513,12 +518,11 @@ def _verify(root: Path) -> int:
513
518
  return _INVALID_EXIT
514
519
  verify_paths = adopted.verify_paths if adopted is not None else (".",)
515
520
  policy = Policy.from_manifest(root, adopted)
516
- if check(
517
- [str(root / path) for path in verify_paths],
518
- policy=policy,
519
- ):
521
+ selected = [str(root / path) for path in verify_paths]
522
+ selected_groups = group_paths(selected, policy=policy)
523
+ if check(selected, policy=policy, grouped=selected_groups):
520
524
  return 1
521
- if check_library_policy(root):
525
+ if check_library_policy(root, python_paths=selected_groups.python):
522
526
  return 1
523
527
  return execute(verification_commands(detect(root)))
524
528
 
@@ -881,10 +885,15 @@ def _selected_external_analysis(
881
885
 
882
886
 
883
887
  def _with_library_policy(
884
- root: Path, native: AnalysisReport, active_selected: list[str], selection_policy: Policy
888
+ root: Path,
889
+ native: AnalysisReport,
890
+ active_selected: list[str],
891
+ selection_policy: Policy,
892
+ *,
893
+ python_paths: Sequence[str] = (),
885
894
  ) -> AnalysisReport:
886
895
  try:
887
- policy = _filter_tool_report(_policy_report(root, active_selected), selection_policy)
896
+ policy = _filter_tool_report(_policy_report(root, active_selected, python_paths=python_paths), selection_policy)
888
897
  except (OSError, TypeError, ValueError, ManifestPolicyError) as exc:
889
898
  issue = ExecutionIssue("sarj-library-policy", "policy-failure", f"{type(exc).__name__}: {exc}")
890
899
  policy = ToolReport("sarj-library-policy", Completion.FAILED, issues=(issue,))
@@ -1137,8 +1146,8 @@ def _engine_for_diagnostic(item: Diagnostic) -> RuleEngine | None:
1137
1146
  }.get(item.source)
1138
1147
 
1139
1148
 
1140
- def _policy_report(root: Path, selected: Sequence[str]) -> ToolReport:
1141
- findings = check_selected_library_policy(root, selected)
1149
+ def _policy_report(root: Path, selected: Sequence[str], *, python_paths: Sequence[str] = ()) -> ToolReport:
1150
+ findings = check_selected_library_policy(root, selected, python_paths=python_paths)
1142
1151
  documents: dict[Path, SourceDocument] = {}
1143
1152
  diagnostics: list[Diagnostic] = []
1144
1153
  for finding in findings:
@@ -3316,6 +3316,6 @@
3316
3316
  },
3317
3317
  "program": "code-standards",
3318
3318
  "schemaVersion": 1,
3319
- "summary": "Adopt, check, fix, diagnose, and update sarj-ai standards (v8.132.2).",
3320
- "version": "8.132.2"
3319
+ "summary": "Adopt, check, fix, diagnose, and update sarj-ai standards (v8.132.4).",
3320
+ "version": "8.132.4"
3321
3321
  }
@@ -19,7 +19,7 @@
19
19
  "@eslint-community/eslint-plugin-eslint-comments": "4.8.1",
20
20
  "@eslint/compat": "2.1.1",
21
21
  "@eslint/js": "10.0.1",
22
- "@sarj/eslint-plugin": "16.30.2",
22
+ "@sarj/eslint-plugin": "16.30.4",
23
23
  "@shadcn/lint": "0.2.3",
24
24
  "@typescript/native": "npm:typescript@7.0.2",
25
25
  "@vitest/eslint-plugin": "1.6.28",
@@ -35,7 +35,6 @@
35
35
  "eslint-plugin-react": "7.37.5",
36
36
  "eslint-plugin-react-hooks": "7.1.1",
37
37
  "eslint-plugin-simple-import-sort": "14.0.0",
38
- "eslint-plugin-sonarjs": "4.2.2",
39
38
  "eslint-plugin-testing-library": "7.16.2",
40
39
  "eslint-plugin-unicorn": "79.0.0",
41
40
  "eslint-plugin-zod": "5.2.2",
@@ -46,7 +45,7 @@
46
45
  "eslint-plugin-regexp": "3.3.1"
47
46
  },
48
47
  "ageGatePreapprovals": {
49
- "@sarj/eslint-plugin": "16.30.2"
48
+ "@sarj/eslint-plugin": "16.30.4"
50
49
  },
51
50
  "yarnIdentityPins": {
52
51
  "@typescript-eslint/eslint-plugin": "8.72.0",
@@ -14,7 +14,6 @@ import node from "eslint-plugin-n";
14
14
  import perfectionist from "eslint-plugin-perfectionist";
15
15
  import promiseModule from "eslint-plugin-promise";
16
16
  import simpleImportSort from "eslint-plugin-simple-import-sort";
17
- import sonarjs from "eslint-plugin-sonarjs";
18
17
  import betterTailwindcss from "eslint-plugin-better-tailwindcss";
19
18
  import { plugin as shadcn, project as shadcnProject } from "@shadcn/lint";
20
19
  import jsdoc from "eslint-plugin-jsdoc";
@@ -693,7 +692,6 @@ export function createConfig(options = {}) {
693
692
  perfectionist,
694
693
  promise,
695
694
  "simple-import-sort": simpleImportSort,
696
- sonarjs,
697
695
  jsdoc,
698
696
  shadcn: scopedShadcn,
699
697
  "@sarj": sarj,
@@ -16,7 +16,6 @@ import perfectionist from "eslint-plugin-perfectionist";
16
16
  // @ts-expect-error -- The pinned promise plugin exports CommonJS without TypeScript declarations.
17
17
  import promiseModule from "eslint-plugin-promise";
18
18
  import simpleImportSort from "eslint-plugin-simple-import-sort";
19
- import sonarjs from "eslint-plugin-sonarjs";
20
19
  import betterTailwindcss from "eslint-plugin-better-tailwindcss";
21
20
  import { plugin as shadcn, project as shadcnProject } from "@shadcn/lint";
22
21
  import jsdoc from "eslint-plugin-jsdoc";
@@ -795,7 +794,6 @@ export function createConfig(options: ConfigOptions = {}): Linter.Config[] {
795
794
  perfectionist,
796
795
  promise,
797
796
  "simple-import-sort": simpleImportSort,
798
- sonarjs,
799
797
  jsdoc,
800
798
  shadcn: scopedShadcn,
801
799
  "@sarj": sarj,
@@ -289,7 +289,6 @@ warns-extend-require-match-for = [
289
289
  "futures".msg = "LIB017: Remove the obsolete futures backport on Python 3.14. Replace with concurrent.futures."
290
290
  "importlib_metadata".msg = "LIB013: Python 3.14 provides importlib.metadata. Replace with importlib.metadata."
291
291
  "importlib_resources".msg = "LIB014: Python 3.14 provides importlib.resources. Replace with importlib.resources."
292
- "logging".msg = "LIB023: Standards standardizes application logging on loguru, whose bound context carries correlation fields to every line; a second stdlib logger splits the logs. A loguru bridge that intercepts third-party stdlib records needs a local, reasoned TID251 suppression. Replace with loguru."
293
292
  "marshmallow".msg = "LIB007: Standards standardizes validation and serialization on Pydantic. Replace with Pydantic."
294
293
  "mock".msg = "LIB022: Python 3.14 provides unittest.mock. Replace with unittest.mock."
295
294
  "nose".msg = "LIB021: Nose is unmaintained; use pytest. Replace with pytest."
@@ -4,6 +4,7 @@ from dataclasses import dataclass
4
4
  import json
5
5
  from pathlib import Path
6
6
  import re
7
+ import tokenize
7
8
  import tomllib
8
9
  from typing import TYPE_CHECKING, Final, Literal, NamedTuple
9
10
 
@@ -11,6 +12,7 @@ from packaging.requirements import InvalidRequirement, Requirement
11
12
  from packaging.utils import canonicalize_name
12
13
 
13
14
  from sarj_standards.libs.adoption.manifest import as_table, list_field
15
+ from sarj_standards.libs.filesystem import is_link_like
14
16
  from sarj_standards.libs.json_boundary import parse_json
15
17
  from sarj_standards.libs.typed_containers import is_object_mapping
16
18
 
@@ -225,9 +227,9 @@ CATALOG: Final[tuple[LibraryMapping, ...]] = (
225
227
  "preferred-stack",
226
228
  "logging",
227
229
  "loguru",
228
- "Standards standardizes application logging on loguru, whose bound context carries correlation fields to "
229
- "every line; a second stdlib logger splits the logs. A loguru bridge that intercepts third-party stdlib "
230
- "records needs a local, reasoned TID251 suppression.",
230
+ "Use Loguru for application-owned log events and standalone output sinks so bound correlation context "
231
+ "stays intact. Standard-library SDK adapters, types, levels and record routing remain supported; "
232
+ "the application preference excludes native test paths without disabling logging correctness checks.",
231
233
  ),
232
234
  _mapping(
233
235
  "LIB101",
@@ -378,7 +380,7 @@ def python_banned_api() -> dict[str, str]:
378
380
  return {
379
381
  name: f"{entry.id}: {entry.message} Replace with {entry.replacement}."
380
382
  for entry in CATALOG
381
- if entry.ecosystem == "python"
383
+ if entry.ecosystem == "python" and entry.id != "LIB023"
382
384
  for name in entry.imports
383
385
  }
384
386
 
@@ -416,6 +418,9 @@ class ManifestPolicyError(ValueError):
416
418
  """An applicable dependency manifest cannot be parsed safely."""
417
419
 
418
420
 
421
+ _MAX_PYTHON_POLICY_SOURCE_BYTES: Final = 500_000
422
+
423
+
419
424
  _IGNORED_DIRS: Final = frozenset(
420
425
  {
421
426
  ".cache",
@@ -448,9 +453,18 @@ _GENERATED_MARKERS: Final = (
448
453
  _REQUIREMENTS_NAME: Final = re.compile(r"^requirements(?:[-_.].*)?\.(?:txt|in)$", re.IGNORECASE)
449
454
 
450
455
 
451
- def scan(root: Path, *, allowed_ids: Iterable[str] = ()) -> tuple[Finding, ...]:
456
+ def scan(
457
+ root: Path,
458
+ *,
459
+ allowed_ids: Iterable[str] = (),
460
+ python_paths: Iterable[str | Path] = (),
461
+ ) -> tuple[Finding, ...]:
452
462
  root = root.resolve()
453
- return _scan_manifests(root, _manifest_paths(root), allowed_ids=allowed_ids)
463
+ allowed = frozenset(allowed_ids)
464
+ return _combined_findings(
465
+ _scan_manifests(root, _manifest_paths(root), allowed_ids=allowed),
466
+ _scan_python_sources(root, python_paths, allowed_ids=allowed),
467
+ )
454
468
 
455
469
 
456
470
  def scan_paths(
@@ -458,8 +472,10 @@ def scan_paths(
458
472
  paths: Iterable[str | Path],
459
473
  *,
460
474
  allowed_ids: Iterable[str] = (),
475
+ python_paths: Iterable[str | Path] = (),
461
476
  ) -> tuple[Finding, ...]:
462
477
  root = root.resolve()
478
+ allowed = frozenset(allowed_ids)
463
479
  selected: set[Path] = set()
464
480
  for raw_path in paths:
465
481
  candidate = Path(raw_path)
@@ -472,7 +488,79 @@ def scan_paths(
472
488
  selected.update(_manifest_paths(resolved))
473
489
  elif resolved.is_file() and accepts_path(resolved, root):
474
490
  selected.add(resolved)
475
- return _scan_manifests(root, tuple(sorted(selected)), allowed_ids=allowed_ids)
491
+ return _combined_findings(
492
+ _scan_manifests(root, tuple(sorted(selected)), allowed_ids=allowed),
493
+ _scan_python_sources(root, python_paths, allowed_ids=allowed),
494
+ )
495
+
496
+
497
+ def _combined_findings(*groups: tuple[Finding, ...]) -> tuple[Finding, ...]:
498
+ return tuple(
499
+ sorted(
500
+ {item for group in groups for item in group},
501
+ key=lambda item: (str(item.path), item.line, item.id, item.package, item.column),
502
+ )
503
+ )
504
+
505
+
506
+ def _scan_python_sources(
507
+ root: Path, paths: Iterable[str | Path], *, allowed_ids: frozenset[str]
508
+ ) -> tuple[Finding, ...]:
509
+ paths = tuple(paths)
510
+ if not paths or "LIB023" in allowed_ids:
511
+ return ()
512
+ from sarj_python_lint import application_logging_uses # ruff: ignore[import-outside-top-level] -- load the public Python preference API only for selected Python source.
513
+
514
+ entry = next(entry for entry in CATALOG if entry.id == "LIB023")
515
+ findings: list[Finding] = []
516
+ selected = {_selected_python_source_path(root, raw_path) for raw_path in paths}
517
+ for path in sorted(selected):
518
+ try:
519
+ with tokenize.open(path) as stream:
520
+ source = stream.read()
521
+ except (SyntaxError, UnicodeError) as exc:
522
+ msg = f"cannot decode selected Python policy source: {path}"
523
+ raise ManifestPolicyError(msg) from exc
524
+ findings.extend(
525
+ Finding(
526
+ entry.id,
527
+ path.relative_to(root),
528
+ use.line,
529
+ use.column,
530
+ "logging",
531
+ entry.replacement,
532
+ f"{entry.message} Observed {use.operation}.",
533
+ )
534
+ for use in application_logging_uses(path, source, root=root)
535
+ )
536
+ return tuple(findings)
537
+
538
+
539
+ def _selected_python_source_path(root: Path, raw_path: str | Path) -> Path:
540
+ candidate = Path(raw_path)
541
+ candidate = candidate if candidate.is_absolute() else root / candidate
542
+ if ".." in candidate.parts:
543
+ msg = f"selected Python policy source escapes repository root: {raw_path}"
544
+ raise ManifestPolicyError(msg)
545
+ try:
546
+ relative = candidate.relative_to(root)
547
+ except ValueError as exc:
548
+ msg = f"selected Python policy source escapes repository root: {raw_path}"
549
+ raise ManifestPolicyError(msg) from exc
550
+ cursor = root
551
+ for part in relative.parts:
552
+ if is_link_like(cursor := cursor / part):
553
+ msg = f"selected Python policy source traverses a symlink: {raw_path}"
554
+ raise ManifestPolicyError(msg)
555
+ path = candidate.resolve(strict=True)
556
+ if (
557
+ not path.is_file()
558
+ or path.suffix not in {".py", ".pyi"}
559
+ or path.stat().st_size > _MAX_PYTHON_POLICY_SOURCE_BYTES
560
+ ):
561
+ msg = f"expected a bounded canonical Python source, not a directory: {raw_path}"
562
+ raise ManifestPolicyError(msg)
563
+ return path
476
564
 
477
565
 
478
566
  def _scan_manifests(
@@ -177,8 +177,9 @@ def run(
177
177
  noise_only: bool = False,
178
178
  python_baseline: str | None = None,
179
179
  policy: Policy | None = None,
180
+ grouped: GroupedPaths | None = None,
180
181
  ) -> int:
181
- grouped = group_paths(files, policy=policy)
182
+ grouped = group_paths(files, policy=policy) if grouped is None else grouped
182
183
  statuses = [
183
184
  _run_tool(
184
185
  "sarj_python_lint",
@@ -343,15 +343,15 @@ def _package_usage(name: str, engine: str | None) -> str:
343
343
  "Python boolean traps are owned by Ruff FBT001, FBT002 and FBT003: positional boolean "
344
344
  "annotations, defaults and literal arguments are checked; keyword-only inputs, named "
345
345
  "arguments and the existing test exemptions remain allowed. The typed ESLint policy "
346
- "uses `@sarj/no-boolean-selector-parameter` at warning severity. This adapter retains "
347
- "maintained SonarJS S2301 detection and adds concise-arrow conditional dispatch. "
346
+ "uses `@sarj/no-boolean-selector-parameter` at warning severity. Its owned detector checks "
347
+ "single-statement operation selectors and concise-arrow conditional dispatch. "
348
348
  "Prefer separate intention-revealing operations or an explicit string-literal mode. "
349
349
  "Boolean data, syntactic value mappings, stable same-operation data choices, "
350
350
  "setters and independently declared callback or inherited contracts remain allowed. "
351
351
  "Independent JSX helpers are checked; types and references establish callback contracts. "
352
352
  "It requires type information and a direct broad-boolean parameter condition. "
353
353
  "Multi-statement bodies, short-circuit guards, nullable or literal-only inputs and "
354
- "indirect predicates remain outside its scope. The inherited upstream block-body "
354
+ "indirect predicates remain outside its scope. The preserved block-body "
355
355
  "`onX` property exemption remains a documented blind spot. Use "
356
356
  "`code-standards check --rule eslint:no-boolean-selector-parameter` to inspect it. "
357
357
  "Noncomputed property reads count as data without proving getter effects; computed "
@@ -20,7 +20,7 @@ from sarj_standards.libs.json_boundary import parse_json
20
20
  from sarj_standards.libs.typed_containers import is_object_mapping
21
21
 
22
22
 
23
- _VERSION: Final = "2.2.1"
23
+ _VERSION: Final = "2.2.2"
24
24
  _CORE_HOOKS: Final = ("pre-commit", "pre-push", "commit-msg")
25
25
  _LFS_POST_HOOKS: Final = ("post-checkout", "post-commit", "post-merge")
26
26
  _DISCOVERY_TIMEOUT: Final = timedelta(seconds=5)