code-standards 8.129.11__tar.gz → 8.131.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 (207) hide show
  1. {code_standards-8.129.11 → code_standards-8.131.0}/PKG-INFO +6 -6
  2. {code_standards-8.129.11 → code_standards-8.131.0}/README.md +1 -1
  3. {code_standards-8.129.11 → code_standards-8.131.0}/pyproject.toml +5 -5
  4. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/api.py +5 -17
  5. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/cli/main.py +151 -43
  6. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/configs/cli-reference.v1.json +14 -3
  7. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/configs/eslint.peers.json +2 -2
  8. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/configs/rule-calibration-campaign.v1.json +14 -6
  9. code_standards-8.131.0/src/sarj_standards/configs/rule-inventory.v1.json +1 -0
  10. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/configs/rule-ledger.json +3 -1
  11. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/libs/adoption/doctor.py +2 -2
  12. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/libs/adoption/hooks.py +5 -6
  13. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/libs/adoption/lifecycle.py +82 -16
  14. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/libs/adoption/scaffold.py +1 -1
  15. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/libs/adoption/transaction.py +62 -10
  16. code_standards-8.131.0/src/sarj_standards/libs/linting/_cloudbuild_autofix.py +134 -0
  17. code_standards-8.131.0/src/sarj_standards/libs/linting/autofix.py +248 -0
  18. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/libs/linting/external.py +20 -13
  19. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/libs/linting/policy.py +9 -0
  20. code_standards-8.131.0/src/sarj_standards/libs/linting/python_fixes.py +39 -0
  21. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/libs/linting/runner.py +88 -17
  22. code_standards-8.131.0/src/sarj_standards/libs/linting/text_rules/cloudbuild_contract.py +136 -0
  23. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/libs/linting/textlint.py +219 -8
  24. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/libs/release/rollout.py +2 -2
  25. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/libs/repository/docs.py +4 -2
  26. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/libs/repository/rule_examples.py +21 -4
  27. code_standards-8.131.0/src/sarj_standards/schemas/rule-catalog.v1.json +1 -0
  28. code_standards-8.129.11/src/sarj_standards/configs/rule-inventory.v1.json +0 -1
  29. code_standards-8.129.11/src/sarj_standards/libs/linting/python_fixes.py +0 -111
  30. code_standards-8.129.11/src/sarj_standards/libs/linting/text_rules/cloudbuild_contract.py +0 -93
  31. code_standards-8.129.11/src/sarj_standards/schemas/rule-catalog.v1.json +0 -1
  32. {code_standards-8.129.11 → code_standards-8.131.0}/.gitignore +0 -0
  33. {code_standards-8.129.11 → code_standards-8.131.0}/LICENSE +0 -0
  34. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/__init__.py +0 -0
  35. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/__main__.py +0 -0
  36. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/_meta.py +0 -0
  37. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/cli/__init__.py +0 -0
  38. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/configs/Mintfile.mobile.strict +0 -0
  39. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/configs/action-parser/LICENSE.actions +0 -0
  40. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/configs/action-parser/LICENSE.cronstrue +0 -0
  41. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/configs/action-parser/LICENSE.yaml +0 -0
  42. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/configs/action-parser/generate.mts +0 -0
  43. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/configs/action-parser/index.mts +0 -0
  44. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/configs/action-parser/package-lock.json +0 -0
  45. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/configs/action-parser/package.json +0 -0
  46. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/configs/action-parser/upstream.json +0 -0
  47. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/configs/action-parser.cjs +0 -0
  48. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/configs/actionlint.strict.yaml +0 -0
  49. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/configs/basedpyright.python315-watch.json +0 -0
  50. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/configs/basedpyright.strict.json +0 -0
  51. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/configs/checkov.strict.yml +0 -0
  52. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/configs/compile-eslint.mts +0 -0
  53. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/configs/detekt.strict.yml +0 -0
  54. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/configs/devops-verification.v1.json +0 -0
  55. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/configs/doctor.config.json +0 -0
  56. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/configs/eslint-compact-formatter.mts +0 -0
  57. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/configs/eslint-required-policy.mts +0 -0
  58. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/configs/eslint-selected-rules.mts +0 -0
  59. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/configs/eslint.application.mjs +0 -0
  60. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/configs/eslint.strict.mjs +0 -0
  61. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/configs/eslint.strict.ts +0 -0
  62. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/configs/hadolint.strict.yaml +0 -0
  63. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/configs/ktlint.strict.editorconfig +0 -0
  64. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/configs/markdownlint.strict.yaml +0 -0
  65. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/configs/mobile-tools.versions.json +0 -0
  66. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/configs/mobsf.strict.yml +0 -0
  67. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/configs/pyright.strict.json +0 -0
  68. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/configs/ruff.application.toml +0 -0
  69. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/configs/ruff.cast.toml +0 -0
  70. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/configs/ruff.python315-watch.toml +0 -0
  71. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/configs/ruff.required.toml +0 -0
  72. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/configs/ruff.strict.toml +0 -0
  73. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/configs/rule-level-source.mts +0 -0
  74. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/configs/schemas/SKAFFOLD-LICENSE +0 -0
  75. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/configs/schemas/google-build-v1-schema.json +0 -0
  76. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/configs/schemas/google-build-v1.LICENSE +0 -0
  77. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/configs/schemas/skaffold-v4beta7.json +0 -0
  78. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/configs/schemas/upstream-schemas.json +0 -0
  79. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/configs/semgrep-overrides.txt +0 -0
  80. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/configs/shellcheck.strict.rc +0 -0
  81. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/configs/swiftformat.strict +0 -0
  82. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/configs/swiftlint.strict.yml +0 -0
  83. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/configs/taplo.strict.toml +0 -0
  84. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/configs/tflint.strict.hcl +0 -0
  85. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/configs/tflint.version.hcl +0 -0
  86. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/configs/tool-json.mts +0 -0
  87. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/configs/yamllint.strict.yaml +0 -0
  88. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/configs/zizmor.strict.yml +0 -0
  89. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/libs/__init__.py +0 -0
  90. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/libs/adoption/__init__.py +0 -0
  91. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/libs/adoption/age_transition.py +0 -0
  92. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/libs/adoption/configs.py +0 -0
  93. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/libs/adoption/devops.py +0 -0
  94. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/libs/adoption/exclusions.py +0 -0
  95. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/libs/adoption/launcher.py +0 -0
  96. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/libs/adoption/manifest.py +0 -0
  97. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/libs/adoption/native_bootstrap.py +0 -0
  98. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/libs/adoption/packagemanager.py +0 -0
  99. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/libs/adoption/repository_baseline.py +0 -0
  100. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/libs/adoption/retired_suppressions.py +0 -0
  101. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/libs/adoption/service.py +0 -0
  102. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/libs/adoption/upgrade.py +0 -0
  103. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/libs/adoption/uvtool.py +0 -0
  104. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/libs/catalogs/__init__.py +0 -0
  105. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/libs/catalogs/slack_automations.py +0 -0
  106. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/libs/corpus/__init__.py +0 -0
  107. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/libs/corpus/manifest.py +0 -0
  108. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/libs/corpus/snapshot.py +0 -0
  109. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/libs/diagnostics/__init__.py +0 -0
  110. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/libs/diagnostics/analysis.schema.json +0 -0
  111. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/libs/diagnostics/baseline.py +0 -0
  112. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/libs/diagnostics/models.py +0 -0
  113. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/libs/diagnostics/serialize.py +0 -0
  114. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/libs/diagnostics/source.py +0 -0
  115. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/libs/filesystem.py +0 -0
  116. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/libs/json_boundary.py +0 -0
  117. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/libs/linting/__init__.py +0 -0
  118. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/libs/linting/action_metadata.py +0 -0
  119. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/libs/linting/analysis.py +0 -0
  120. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/libs/linting/chart_schemas.py +0 -0
  121. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/libs/linting/cloudbuild.py +0 -0
  122. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/libs/linting/cloudbuild_schema.py +0 -0
  123. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/libs/linting/complexity_baseline.py +0 -0
  124. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/libs/linting/devops_programs.py +0 -0
  125. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/libs/linting/devops_schema.py +0 -0
  126. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/libs/linting/devops_source.py +0 -0
  127. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/libs/linting/devops_tools.py +0 -0
  128. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/libs/linting/duplicate_code.py +0 -0
  129. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/libs/linting/embedded_shell.py +0 -0
  130. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/libs/linting/kubernetes_context.py +0 -0
  131. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/libs/linting/library_policy.py +0 -0
  132. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/libs/linting/mobile_tools.py +0 -0
  133. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/libs/linting/prepared_devops.py +0 -0
  134. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/libs/linting/prepared_kubernetes.py +0 -0
  135. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/libs/linting/prepared_native.py +0 -0
  136. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/libs/linting/repo_standards.py +0 -0
  137. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/libs/linting/scheduling.py +0 -0
  138. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/libs/linting/security_tools.py +0 -0
  139. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/libs/linting/shell_ast.py +0 -0
  140. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/libs/linting/shell_format.py +0 -0
  141. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/libs/linting/shell_policy.py +0 -0
  142. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/libs/linting/test_value.py +0 -0
  143. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/libs/linting/text_rule_base.py +0 -0
  144. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/libs/linting/text_rules/__init__.py +0 -0
  145. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/libs/linting/text_rules/_registry.py +0 -0
  146. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/libs/linting/toml_literals.py +0 -0
  147. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/libs/linting/unused_modules.py +0 -0
  148. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/libs/release/__init__.py +0 -0
  149. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/libs/release/_values.py +0 -0
  150. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/libs/release/artifacts.py +0 -0
  151. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/libs/release/causality.py +0 -0
  152. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/libs/release/changes.py +0 -0
  153. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/libs/release/ci_artifacts.py +0 -0
  154. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/libs/release/make_checks.py +0 -0
  155. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/libs/release/metadata_verification.py +0 -0
  156. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/libs/release/native_test_setup.py +0 -0
  157. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/libs/release/process.py +0 -0
  158. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/libs/release/publish.py +0 -0
  159. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/libs/release/registry.py +0 -0
  160. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/libs/release/release_age.py +0 -0
  161. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/libs/release/release_detect.py +0 -0
  162. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/libs/release/retirement.py +0 -0
  163. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/libs/release/reviewed_analysis.py +0 -0
  164. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/libs/release/status.py +0 -0
  165. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/libs/release/tags.py +0 -0
  166. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/libs/release/test_selection.py +0 -0
  167. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/libs/release/typescript.py +0 -0
  168. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/libs/release/verification_process.py +0 -0
  169. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/libs/release/wheel_tests.py +0 -0
  170. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/libs/repository/__init__.py +0 -0
  171. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/libs/repository/cli_reference_artifact.py +0 -0
  172. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/libs/repository/cloudbuild_schema_projection.py +0 -0
  173. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/libs/repository/comment_corpus.py +0 -0
  174. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/libs/repository/config_generation.py +0 -0
  175. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/libs/repository/hooks.py +0 -0
  176. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/libs/repository/immutable_git.py +0 -0
  177. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/libs/repository/ledger.py +0 -0
  178. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/libs/repository/repository.py +0 -0
  179. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/libs/repository/ruff_freshness.py +0 -0
  180. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/libs/repository/rule_authoring.py +0 -0
  181. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/libs/repository/rule_catalog_artifact.py +0 -0
  182. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/libs/repository/rule_changes.py +0 -0
  183. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/libs/repository/rule_checkout.py +0 -0
  184. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/libs/repository/rule_dependencies.py +0 -0
  185. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/libs/repository/rule_imports.mts +0 -0
  186. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/libs/repository/rule_inventory_artifact.py +0 -0
  187. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/libs/repository/rule_level_source.py +0 -0
  188. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/libs/repository/rule_lifecycle.py +0 -0
  189. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/libs/repository/rule_maintenance.py +0 -0
  190. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/libs/repository/rule_registration.py +0 -0
  191. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/libs/repository/shell_checks.py +0 -0
  192. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/libs/repository/third_party_catalog_artifact.py +0 -0
  193. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/libs/rules/__init__.py +0 -0
  194. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/libs/rules/catalog.py +0 -0
  195. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/libs/rules/contracts.py +0 -0
  196. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/libs/rules/corpus_runner.py +0 -0
  197. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/libs/rules/evaluation.py +0 -0
  198. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/libs/schema_boundary.py +0 -0
  199. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/libs/setup/__init__.py +0 -0
  200. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/libs/setup/repository.py +0 -0
  201. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/libs/typed_containers.py +0 -0
  202. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/libs/yaml_boundary.py +0 -0
  203. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/py.typed +0 -0
  204. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/schemas/__init__.py +0 -0
  205. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/schemas/_paths.py +0 -0
  206. {code_standards-8.129.11 → code_standards-8.131.0}/src/sarj_standards/schemas/rule-catalog.v1.schema.json +0 -0
  207. {code_standards-8.129.11 → code_standards-8.131.0}/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.129.11
3
+ Version: 8.131.0
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/
@@ -30,10 +30,10 @@ Requires-Dist: pyyaml==6.0.3
30
30
  Requires-Dist: referencing==0.37.0
31
31
  Requires-Dist: repo-standards==6.12.9
32
32
  Requires-Dist: ruff==0.17.2
33
- Requires-Dist: sarj-iac-lint==0.29.1
34
- Requires-Dist: sarj-python-lint==1.74.2
35
- Requires-Dist: sarj-rule-contracts==0.2.6
36
- Requires-Dist: sarj-sql-lint==0.25.1
33
+ Requires-Dist: sarj-iac-lint==0.30.1
34
+ Requires-Dist: sarj-python-lint==1.76.0
35
+ Requires-Dist: sarj-rule-contracts==0.4.1
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')
38
38
  Requires-Dist: typer==0.27.3
39
39
  Description-Content-Type: text/markdown
@@ -50,7 +50,7 @@ uv tool install --python 3.15 code-standards
50
50
 
51
51
  Adopt the repository once with `code-standards setup`. It installs one canonical staged gate that includes semantic lint and repository policy, plus commit-message and pull-request history enforcement. Do not install Repo Standards separately.
52
52
 
53
- The pre-commit gate runs once on every commit and discovers paths directly from the Git index, including mixed file types and deletion-only commits. The shared dispatcher selects applicable rules and retains type analysis, repository policy, exclusions and suppression accountability. Errors and incomplete analysis block the commit; warning-stage findings stay visible even when the hook passes. Agents should address the diagnostics, run `code-standards fix --staged` for safe mechanical fixes, review and stage intended edits, then retry. Staged fixes never fall back to the whole repository and refuse files with unstaged changes.
53
+ The pre-commit gate runs once on every commit and discovers paths directly from the Git index, including mixed file types and deletion-only commits. The shared dispatcher selects applicable rules and retains type analysis, repository policy, exclusions and suppression accountability. Errors and incomplete analysis block the commit; warning-stage findings stay visible even when the hook passes. Generated hooks apply safe custom-rule, Ruff and ESLint fixes automatically. When a fix changes a staged file, the gate stops so you can review and stage the edit, then retry. Use `code-standards fix --staged` to apply fixes separately, or `check --fix` to fix before checking. Staged fixes never fall back to the whole repository and refuse files with unstaged changes.
54
54
 
55
55
  Setup installs the selected hook manager. In a fresh checkout, run `code-standards doctor --repair` before committing; doctor checks installation and the exact unconditional command. Conditional Lefthook jobs must be moved to an unconditional job without changing unrelated hooks. Git can bypass local hooks with `--no-verify`; the canonical CI gate independently enforces policy.
56
56
 
@@ -10,7 +10,7 @@ uv tool install --python 3.15 code-standards
10
10
 
11
11
  Adopt the repository once with `code-standards setup`. It installs one canonical staged gate that includes semantic lint and repository policy, plus commit-message and pull-request history enforcement. Do not install Repo Standards separately.
12
12
 
13
- The pre-commit gate runs once on every commit and discovers paths directly from the Git index, including mixed file types and deletion-only commits. The shared dispatcher selects applicable rules and retains type analysis, repository policy, exclusions and suppression accountability. Errors and incomplete analysis block the commit; warning-stage findings stay visible even when the hook passes. Agents should address the diagnostics, run `code-standards fix --staged` for safe mechanical fixes, review and stage intended edits, then retry. Staged fixes never fall back to the whole repository and refuse files with unstaged changes.
13
+ The pre-commit gate runs once on every commit and discovers paths directly from the Git index, including mixed file types and deletion-only commits. The shared dispatcher selects applicable rules and retains type analysis, repository policy, exclusions and suppression accountability. Errors and incomplete analysis block the commit; warning-stage findings stay visible even when the hook passes. Generated hooks apply safe custom-rule, Ruff and ESLint fixes automatically. When a fix changes a staged file, the gate stops so you can review and stage the edit, then retry. Use `code-standards fix --staged` to apply fixes separately, or `check --fix` to fix before checking. Staged fixes never fall back to the whole repository and refuse files with unstaged changes.
14
14
 
15
15
  Setup installs the selected hook manager. In a fresh checkout, run `code-standards doctor --repair` before committing; doctor checks installation and the exact unconditional command. Conditional Lefthook jobs must be moved to an unconditional job without changing unrelated hooks. Git can bypass local hooks with `--no-verify`; the canonical CI gate independently enforces policy.
16
16
 
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "code-standards"
3
- version = "8.129.11"
3
+ version = "8.131.0"
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"
@@ -17,7 +17,7 @@ classifiers = [
17
17
  "Topic :: Software Development :: Quality Assurance",
18
18
  ]
19
19
  dependencies = [
20
- "sarj-rule-contracts==0.2.6",
20
+ "sarj-rule-contracts==0.4.1",
21
21
  "pathspec==1.1.1",
22
22
  "basedpyright==1.40.2",
23
23
  "deptry==0.25.1",
@@ -31,9 +31,9 @@ dependencies = [
31
31
  "repo-standards==6.12.9",
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
- "sarj-iac-lint==0.29.1",
35
- "sarj-python-lint==1.74.2",
36
- "sarj-sql-lint==0.25.1",
34
+ "sarj-iac-lint==0.30.1",
35
+ "sarj-python-lint==1.76.0",
36
+ "sarj-sql-lint==0.26.1",
37
37
  "typer==0.27.3",
38
38
  ]
39
39
 
@@ -391,31 +391,19 @@ class Standards:
391
391
  ) -> AnalysisReport:
392
392
  return self.analyze(paths, external=external, trust=trust, mode=mode, rules=rules, staged=staged, jobs=jobs)
393
393
 
394
- def fix(self) -> Result:
395
- from .libs.adoption import ( # ruff: ignore[import-outside-top-level] -- selected operation only
396
- lifecycle,
397
- scaffold,
398
- )
399
- from .libs.linting.python_fixes import fix_python # ruff: ignore[import-outside-top-level] -- only fix needs native edit application.
394
+ def fix(self, paths: Sequence[str] | None = None) -> Result:
395
+ from .libs.linting import autofix # ruff: ignore[import-outside-top-level] -- selected operation only.
400
396
 
401
397
  try:
402
- adopted = load_manifest(self.root)
403
- ecosystems = scaffold.detect(self.root) if adopted is None else scaffold.detect_adopted(self.root, adopted)
404
- if ecosystems.python_root is not None:
405
- selected = [str(self.root / path) for path in (adopted.verify_paths if adopted is not None else (".",))]
406
- fix_python(
407
- selected,
408
- root=self.root,
409
- policy=Policy.from_manifest(self.root, adopted),
410
- python_root=ecosystems.python_root,
411
- )
398
+ selected = [str(self.root / path) for path in paths] if paths is not None else [str(self.root)]
399
+ result = autofix.run(self.root, selected, trusted=True, default_scope=paths is None)
412
400
  except (OSError, SyntaxError, TypeError, UnicodeError, ValueError) as exc:
413
401
  return Result(
414
402
  Status.INVALID,
415
403
  findings=(Finding("fix.input.invalid", "error", str(exc)),),
416
404
  exit_code=_INVALID_EXIT,
417
405
  )
418
- return _operation_result(lifecycle.execute(lifecycle.format_commands(ecosystems, root=self.root)))
406
+ return _operation_result(result.status)
419
407
 
420
408
  def doctor(self) -> Result:
421
409
  diagnosed = diagnose(self.root)
@@ -40,6 +40,7 @@ if TYPE_CHECKING:
40
40
 
41
41
  from sarj_standards.libs.adoption import doctor, lifecycle, service, upgrade
42
42
  from sarj_standards.libs.diagnostics import AnalysisReport, Diagnostic, ExecutionIssue
43
+ from sarj_standards.libs.linting import autofix
43
44
  from sarj_standards.libs.linting.external import UpstreamESLintRules
44
45
  from sarj_standards.libs.repository import rule_catalog_artifact
45
46
 
@@ -180,6 +181,7 @@ class _Args:
180
181
  exclude_kind: str = ""
181
182
  value: str = ""
182
183
  staged: bool = False
184
+ fix: bool = False
183
185
  release_commit: str = ""
184
186
  max_annotations_per_level: int = 10
185
187
  analysis_mode: str = "policy"
@@ -1119,9 +1121,15 @@ def cmd_library_policy(args: _Args, *, selected_paths: Iterable[str] | None = No
1119
1121
 
1120
1122
 
1121
1123
  def cmd_check(args: _Args) -> int:
1122
- from sarj_standards.libs.linting import runner # ruff: ignore[import-outside-top-level] -- load sarj_standards.libs.linting only when this selected operation executes.
1123
-
1124
1124
  root = _resolve_dest(args.dest)
1125
+ if args.fix and args.selected_rules:
1126
+ print(
1127
+ "error: --fix applies the complete configured rule set; omit --rule or run check without --fix",
1128
+ file=sys.stderr,
1129
+ )
1130
+ return 2
1131
+ if args.fix and _validate_analysis_output(args, root):
1132
+ return 2
1125
1133
  catalog_status = 0 if args.selected_rules else _check_conventional_slack_catalog(args, root)
1126
1134
  if catalog_status:
1127
1135
  return catalog_status
@@ -1134,14 +1142,29 @@ def cmd_check(args: _Args) -> int:
1134
1142
  scope.repository_wide = True
1135
1143
  if args.selected_rules:
1136
1144
  return _check_selected_rules(args, root, scope)
1145
+ preparation_status = _prepare_check_inputs(args, root, scope)
1146
+ if preparation_status is not None:
1147
+ return preparation_status
1148
+ if args.output_format != "text":
1149
+ return _check_machine_output(args, root, scope)
1150
+ return _check_text_output(args, root, scope)
1151
+
1152
+
1153
+ def _prepare_check_inputs(args: _Args, root: Path, scope: _CheckScope) -> int | None:
1154
+ from sarj_standards.libs.linting import runner # ruff: ignore[import-outside-top-level] -- source routing is needed only for check execution.
1155
+
1137
1156
  if args.staged:
1138
1157
  health_status = _check_staged_adoption_health(root, args.files, args=args)
1139
1158
  if health_status:
1140
1159
  return health_status
1141
1160
  args.files = [path for path in args.files if runner.accepts_hook_path(Path(path), root=root)]
1142
- if args.output_format != "text":
1143
- return _check_machine_output(args, root, scope)
1144
- return _check_text_output(args, root, scope)
1161
+ if args.fix:
1162
+ result = _apply_safe_fixes(root, args.files, args=args, scoped=args.staged or scope.pull_request_scoped)
1163
+ if result.status > 1:
1164
+ return _emit_fix_failure(args, root, result.status)
1165
+ if result.changed and args.staged:
1166
+ return _emit_fix_review_required(args, root)
1167
+ return None
1145
1168
 
1146
1169
 
1147
1170
  def _check_selected_rules(args: _Args, root: Path, scope: _CheckScope) -> int:
@@ -1236,7 +1259,7 @@ def _select_staged_check(args: _Args, root: Path, scope: _CheckScope) -> int | N
1236
1259
  try:
1237
1260
  staged_names = _staged_file_names(root)
1238
1261
  scope.react_doctor_triggered = _react_doctor_triggered_by(staged_names)
1239
- staged = _safe_staged_paths(root, staged_names)
1262
+ staged = _safe_staged_paths(root, _staged_file_names(root, include_deleted=False))
1240
1263
  except (OSError, subprocess.SubprocessError) as exc:
1241
1264
  if args.output_format != "text":
1242
1265
  return _emit_analysis_report(args, root, _machine_input_error(root, f"cannot read staged files: {exc}"))
@@ -1246,15 +1269,21 @@ def _select_staged_check(args: _Args, root: Path, scope: _CheckScope) -> int | N
1246
1269
  requested = frozenset(_repository_relative_names(root, args.files))
1247
1270
  selected_staged_names = [name for name in staged_names if name in requested]
1248
1271
  staged_set = frozenset(staged)
1249
- args.files = [path for path in _safe_staged_paths(root, args.files) if path in staged_set]
1272
+ args.files = _requested_staged_paths(root, args.files, staged=staged_set)
1250
1273
  else:
1251
1274
  selected_staged_names = staged_names
1252
1275
  args.files = staged
1253
- drifted = _unstaged_versions(root, selected_staged_names)
1276
+ try:
1277
+ drifted = _unstaged_versions(root, selected_staged_names)
1278
+ except (OSError, subprocess.SubprocessError) as exc:
1279
+ if args.output_format != "text":
1280
+ return _emit_analysis_report(args, root, _machine_input_error(root, f"cannot read staged files: {exc}"))
1281
+ print(f"error: cannot read staged files: {exc}", file=sys.stderr)
1282
+ return 2
1254
1283
  if drifted:
1255
1284
  message = (
1256
- "--staged found files with unstaged content; run through pre-commit "
1257
- "(which safely stashes it) or stage the intended versions: " + ", ".join(drifted)
1285
+ "--staged found files with unstaged content or unverifiable Git index flags; "
1286
+ "stage the intended versions and clear assume-unchanged/skip-worktree flags: " + ", ".join(drifted)
1258
1287
  )
1259
1288
  if args.output_format != "text":
1260
1289
  return _emit_analysis_report(args, root, _machine_input_error(root, message))
@@ -1263,6 +1292,10 @@ def _select_staged_check(args: _Args, root: Path, scope: _CheckScope) -> int | N
1263
1292
  return None
1264
1293
 
1265
1294
 
1295
+ def _requested_staged_paths(root: Path, files: Sequence[str], *, staged: frozenset[str]) -> list[str]:
1296
+ return [path for path in _safe_staged_paths(root, files) if path in staged]
1297
+
1298
+
1266
1299
  def _select_explicit_check(args: _Args, root: Path) -> int | None:
1267
1300
  try:
1268
1301
  args.files = _selected_paths(root, args.files)
@@ -2069,13 +2102,16 @@ def _emit_staged_adoption_health(args: _Args, root: Path, drifted: list[doctor.F
2069
2102
  return _emit_analysis_report(args, root, report)
2070
2103
 
2071
2104
 
2072
- def _staged_file_names(root: Path) -> list[str]:
2105
+ def _staged_file_names(root: Path, *, include_deleted: bool = True) -> list[str]:
2073
2106
  git = shutil.which("git")
2074
2107
  if git is None:
2075
2108
  msg = "git is required for --staged"
2076
2109
  raise OSError(msg)
2110
+ command = [git, "diff", "--cached", "--name-only", "-z"]
2111
+ if not include_deleted:
2112
+ command.append("--diff-filter=ACMRT")
2077
2113
  completed = subprocess.run( # ruff: ignore[subprocess-without-shell-equals-true] -- fixed argv, no shell.
2078
- [git, "diff", "--cached", "--name-only", "-z"],
2114
+ command,
2079
2115
  cwd=root,
2080
2116
  check=True,
2081
2117
  capture_output=True,
@@ -2152,6 +2188,19 @@ def _unstaged_versions(root: Path, staged_paths: Iterable[str]) -> tuple[str, ..
2152
2188
  )
2153
2189
  unstaged = {part.decode("utf-8", errors="surrogateescape") for part in completed.stdout.split(b"\0") if part}
2154
2190
  selected = set(_repository_relative_names(root, staged_paths))
2191
+ if selected:
2192
+ tracked = subprocess.run( # ruff: ignore[subprocess-without-shell-equals-true] -- literal selected paths and NUL records preserve authored filenames.
2193
+ [git, "--literal-pathspecs", "ls-files", "-v", "-z", "--", *sorted(selected)],
2194
+ cwd=root,
2195
+ check=True,
2196
+ capture_output=True,
2197
+ env=_git_environment(),
2198
+ )
2199
+ unstaged.update(
2200
+ entry[2:].decode("utf-8", errors="surrogateescape")
2201
+ for entry in tracked.stdout.split(b"\0")
2202
+ if entry and (b"a" <= entry[:1] <= b"z" or entry[:1] == b"S")
2203
+ )
2155
2204
  return tuple(sorted(unstaged & selected))
2156
2205
 
2157
2206
 
@@ -2211,7 +2260,7 @@ def _selected_paths(root: Path, paths: Iterable[str]) -> list[str]:
2211
2260
 
2212
2261
 
2213
2262
  def cmd_format(args: _Args) -> int:
2214
- from sarj_standards.libs.adoption import doctor # ruff: ignore[import-outside-top-level] -- selected operation only.
2263
+ from sarj_standards.libs.adoption import doctor # ruff: ignore[import-outside-top-level] -- diagnosis gates an explicit fix operation.
2215
2264
 
2216
2265
  root = _resolve_dest(args.dest)
2217
2266
  diagnosed = doctor.diagnose(root)
@@ -2234,45 +2283,84 @@ def cmd_format(args: _Args) -> int:
2234
2283
  except ValueError as exc:
2235
2284
  print(f"error: {exc}", file=sys.stderr)
2236
2285
  return 2
2237
- return _execute_fixes(root, args.files, _declared_manifest(args))
2286
+ return _apply_safe_fixes(root, args.files, args=args, trusted=True).status
2238
2287
 
2239
2288
 
2240
- def _execute_fixes(root: Path, files: list[str], adopted: manifest.Manifest | None) -> int:
2241
- from sarj_standards.libs.adoption import lifecycle, scaffold # ruff: ignore[import-outside-top-level] -- selected operation only.
2242
- from sarj_standards.libs.linting.python_fixes import fix_python # ruff: ignore[import-outside-top-level] -- native edits precede upstream rewrites.
2289
+ def _apply_safe_fixes(
2290
+ root: Path, files: Sequence[str], *, args: _Args, trusted: bool = False, scoped: bool = False
2291
+ ) -> autofix.FixResult:
2292
+ from sarj_standards.libs.linting import autofix # ruff: ignore[import-outside-top-level] -- native fixers are not needed for read-only checks.
2243
2293
 
2244
- ecosystems = scaffold.detect(root) if adopted is None else scaffold.detect_adopted(root, adopted)
2245
- selected = files or [str(root / path) for path in (adopted.verify_paths if adopted is not None else (".",))]
2294
+ requested = files if files or scoped else [str(root)]
2246
2295
  try:
2247
- if files:
2248
- fix_python(
2249
- [path for path in files if Path(path).is_file()], root=root, policy=Policy.from_manifest(root, adopted)
2250
- )
2251
- elif ecosystems.python_root is not None:
2252
- fix_python(
2253
- selected, root=root, policy=Policy.from_manifest(root, adopted), python_root=ecosystems.python_root
2254
- )
2296
+ return autofix.run(
2297
+ root,
2298
+ requested,
2299
+ trusted=trusted or args.trust_repository_code,
2300
+ eslint=args.eslint,
2301
+ machine_output=args.output_format != "text",
2302
+ default_scope=not files and not scoped,
2303
+ )
2255
2304
  except (OSError, SyntaxError, UnicodeError, ValueError) as exc:
2256
- print(f"error: native Python fixes failed: {exc}", file=sys.stderr)
2257
- return 2
2258
- commands = (
2259
- lifecycle.selected_format_commands(root, files) if files else lifecycle.format_commands(ecosystems, root=root)
2305
+ print(f"error: cannot apply safe fixes: {exc}", file=sys.stderr)
2306
+ return autofix.FixResult(2, ())
2307
+
2308
+
2309
+ def _emit_fix_failure(args: _Args, root: Path, status: int) -> int:
2310
+ if args.output_format == "text":
2311
+ return status
2312
+ from sarj_standards.libs.diagnostics import ( # ruff: ignore[import-outside-top-level] -- failed fixes must preserve the requested machine report contract.
2313
+ Completion,
2314
+ ExecutionIssue,
2315
+ ToolReport,
2316
+ )
2317
+ from sarj_standards.libs.linting.analysis import report_from_tools # ruff: ignore[import-outside-top-level] -- use the existing analysis output contract.
2318
+
2319
+ issue = ExecutionIssue(
2320
+ "sarj-standards-autofix",
2321
+ "autofix-failed",
2322
+ "Safe-fix execution failed. Review any applied changes and the tool error output, then retry.",
2323
+ exit_code=status,
2324
+ )
2325
+ report = report_from_tools(root, (ToolReport("sarj-standards-autofix", Completion.FAILED, issues=(issue,)),))
2326
+ return _emit_analysis_report(args, root, report)
2327
+
2328
+
2329
+ def _emit_fix_review_required(args: _Args, root: Path) -> int:
2330
+ message = "Safe fixes applied. Review and stage the changes, then retry the commit."
2331
+ if args.output_format == "text":
2332
+ print(message, file=sys.stderr)
2333
+ return 1
2334
+ from sarj_standards.libs.diagnostics import ( # ruff: ignore[import-outside-top-level] -- structured results are needed only for machine output.
2335
+ Completion,
2336
+ Diagnostic,
2337
+ Location,
2338
+ Severity,
2339
+ ToolReport,
2340
+ )
2341
+ from sarj_standards.libs.linting.analysis import report_from_tools # ruff: ignore[import-outside-top-level] -- use the existing analysis output contract.
2342
+
2343
+ diagnostic = Diagnostic(
2344
+ "fix.review-required",
2345
+ message,
2346
+ Severity.ERROR,
2347
+ "sarj-standards-autofix",
2348
+ Location("."),
2349
+ rule_id="fix.review-required",
2350
+ help="Review and stage the changes, then retry the commit.",
2260
2351
  )
2261
- return lifecycle.execute(commands)
2352
+ report = report_from_tools(
2353
+ root, (ToolReport("sarj-standards-autofix", Completion.COMPLETE, diagnostics=(diagnostic,)),)
2354
+ )
2355
+ return _emit_analysis_report(args, root, report)
2262
2356
 
2263
2357
 
2264
2358
  def _select_staged_fix(args: _Args, root: Path) -> int | None:
2265
2359
  try:
2266
- staged_names = _staged_file_names(root)
2267
- drifted = _unstaged_versions(root, staged_names)
2268
- if drifted:
2269
- print(
2270
- "error: --staged found files with unstaged content; stage the intended versions before fixing: "
2271
- + ", ".join(drifted),
2272
- file=sys.stderr,
2273
- )
2274
- return 2
2275
- args.files = _safe_staged_paths(root, staged_names)
2360
+ args.files = _staged_fix_paths(root, args.files)
2361
+ except ValueError as exc:
2362
+ print(f"error: {exc}", file=sys.stderr)
2363
+ return 2
2276
2364
  except (OSError, subprocess.SubprocessError) as exc:
2277
2365
  print(f"error: cannot read staged files: {exc}", file=sys.stderr)
2278
2366
  return 2
@@ -2282,8 +2370,23 @@ def _select_staged_fix(args: _Args, root: Path) -> int | None:
2282
2370
  return None
2283
2371
 
2284
2372
 
2373
+ def _staged_fix_paths(root: Path, files: Sequence[str]) -> list[str]:
2374
+ staged_names = _staged_file_names(root, include_deleted=False)
2375
+ if files:
2376
+ requested = set(_repository_relative_names(root, files))
2377
+ staged_names = [name for name in staged_names if name in requested]
2378
+ if drifted := _unstaged_versions(root, staged_names):
2379
+ msg = (
2380
+ "--staged found files with unstaged content or unverifiable Git index flags; "
2381
+ "stage the intended versions and clear assume-unchanged/skip-worktree flags before fixing: "
2382
+ + ", ".join(drifted)
2383
+ )
2384
+ raise ValueError(msg)
2385
+ return _safe_staged_paths(root, staged_names)
2386
+
2387
+
2285
2388
  def _staged_files(root: Path) -> list[str]:
2286
- return _safe_staged_paths(root, _staged_file_names(root))
2389
+ return _safe_staged_paths(root, _staged_file_names(root, include_deleted=False))
2287
2390
 
2288
2391
 
2289
2392
  def cmd_inspect(args: _Args) -> int:
@@ -3167,6 +3270,10 @@ def build_app(handler: Callable[[_Args], int] = _dispatch) -> typer.Typer:
3167
3270
  help="run the complete gate on staged files; optional paths narrow the staged selection",
3168
3271
  ),
3169
3272
  ] = False,
3273
+ fix: Annotated[
3274
+ bool,
3275
+ typer.Option("--fix", help="apply safe fixes before checking; staged edits remain unstaged for review"),
3276
+ ] = False,
3170
3277
  selected_rules: Annotated[
3171
3278
  list[RuleSelector] | None,
3172
3279
  typer.Option(
@@ -3189,6 +3296,7 @@ def build_app(handler: Callable[[_Args], int] = _dispatch) -> typer.Typer:
3189
3296
  eslint=not skip_eslint,
3190
3297
  trust_repository_code=trust_repository_code,
3191
3298
  staged=staged,
3299
+ fix=fix,
3192
3300
  selected_rules=selected_rules if selected_rules is not None else [],
3193
3301
  output_format=output_format.value,
3194
3302
  output=output if output is not None else None,
@@ -454,6 +454,17 @@
454
454
  "required": false,
455
455
  "summary": "run the complete gate on staged files; optional paths narrow the staged selection"
456
456
  },
457
+ {
458
+ "choices": [],
459
+ "kind": "option",
460
+ "metavar": null,
461
+ "names": [
462
+ "--fix"
463
+ ],
464
+ "repeatable": false,
465
+ "required": false,
466
+ "summary": "apply safe fixes before checking; staged edits remain unstaged for review"
467
+ },
457
468
  {
458
469
  "choices": [],
459
470
  "kind": "option",
@@ -519,7 +530,7 @@
519
530
  "check"
520
531
  ],
521
532
  "summary": "run the complete quality gate or check selected paths or custom rules",
522
- "usage": "code-standards check [-h] [--trust-repository-code] [--jobs JOBS] [--skip-python-type-check] [--skip-eslint] [--staged] [--rule SELECTED_RULES ...] [--format OUTPUT_FORMAT] [--output OUTPUT] [--max-annotations-per-level MAX_ANNOTATIONS_PER_LEVEL] [FILES ...]"
533
+ "usage": "code-standards check [-h] [--trust-repository-code] [--jobs JOBS] [--skip-python-type-check] [--skip-eslint] [--staged] [--fix] [--rule SELECTED_RULES ...] [--format OUTPUT_FORMAT] [--output OUTPUT] [--max-annotations-per-level MAX_ANNOTATIONS_PER_LEVEL] [FILES ...]"
523
534
  },
524
535
  {
525
536
  "commands": [],
@@ -3305,6 +3316,6 @@
3305
3316
  },
3306
3317
  "program": "code-standards",
3307
3318
  "schemaVersion": 1,
3308
- "summary": "Adopt, check, fix, diagnose, and update sarj-ai standards (v8.129.11).",
3309
- "version": "8.129.11"
3319
+ "summary": "Adopt, check, fix, diagnose, and update sarj-ai standards (v8.131.0).",
3320
+ "version": "8.131.0"
3310
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.29.0",
22
+ "@sarj/eslint-plugin": "16.30.0",
23
23
  "@shadcn/lint": "0.2.3",
24
24
  "@typescript/native": "npm:typescript@7.0.2",
25
25
  "@vitest/eslint-plugin": "1.6.28",
@@ -46,7 +46,7 @@
46
46
  "eslint-plugin-regexp": "3.3.1"
47
47
  },
48
48
  "ageGatePreapprovals": {
49
- "@sarj/eslint-plugin": "16.29.0"
49
+ "@sarj/eslint-plugin": "16.30.0"
50
50
  },
51
51
  "yarnIdentityPins": {
52
52
  "@typescript-eslint/eslint-plugin": "8.72.0",
@@ -805,8 +805,8 @@
805
805
  "family": "python",
806
806
  "ruleId": "prefer-fstring-over-concat",
807
807
  "state": "complete",
808
- "evidence": "Three independent reviews ran 75 focused cases and scanned 7,098 tracked first-party Python files across 85 repositories plus a normalized 462-file Pygments and pytest corpus. The original broad rule produced 39 first-party findings with 17 bad recommendations and 130 popular-source findings dominated by regex, style-table, ANSI, path, identifier, and protocol fragments. Final calibration produced seven first-party and eleven popular-source warnings; all 18 were inspected as defensible human-readable interpolation improvements, with zero observed false positives or scanner errors. Additional strict-policy campaign (2026-10-13): pass 10 of 30 is hold-warning. Annotated str may be a subclass with different __add__ and __format__ behavior; current broad detector does not prove builtin-string operands. Reproducible final calibration, judge and performance evidence is recorded in packages/python/benchmarks/error-promotion-third-30-passes.json.",
809
- "outcome": "Kept the compatible prefer-fstring-over-concat name and staged SARJ068 as a warning. Narrowed it to short prose-like interpolation inside callable scopes with proven string operands; added conservative binding and import provenance, late-rebinding kills, and exclusions for generated code, logging, common SQL and regex forms, long literals, module and class declarations, URL and path fragments, units, filenames, identifiers, protocol punctuation, lazy strings, and ORM expressions. Removed arbitrary operand-count join advice and comment bypasses. The UI now preserves explicit str and repr semantics with !s and !r instead of claiming wrappers can disappear."
808
+ "evidence": "Three independent reviews ran 75 focused cases and scanned 7,098 tracked first-party Python files across 85 repositories plus a normalized 462-file Pygments and pytest corpus. The original broad rule produced 39 first-party findings with 17 bad recommendations and 130 popular-source findings dominated by regex, style-table, ANSI, path, identifier, and protocol fragments. Final calibration produced seven first-party and eleven popular-source warnings; all 18 were inspected as defensible human-readable interpolation improvements, with zero observed false positives or scanner errors. Additional strict-policy campaign (2026-10-13): pass 10 of 30 is hold-warning. Annotated str may be a subclass with different __add__ and __format__ behavior; current broad detector does not prove builtin-string operands. Reproducible final calibration, judge and performance evidence is recorded in packages/python/benchmarks/error-promotion-third-30-passes.json. Follow-up: packages/python/benchmarks/service-contracts-and-ids-100-passes.json records 100 distinct semantic cases (39 true positives, 61 true negatives, no labeled false positives/negatives), five exact motivating blocking findings, deterministic three-trial cold/warm measurements on 296 guarded sample files, and completed local canonical gates. Private source and identifying pins remain local. Exact-head CI and broader review remain separate gates.",
809
+ "outcome": "Enforce supported short human-readable interpolation at ERROR, including stable named literal prefixes. This is a stricter reviewed style policy; str annotations do not prove custom operator/formatting equivalence, so required custom semantics retain exact reasoned exceptions. Source/configuration fragments, stable join aliases and other documented structural exclusions remain valid. Keep only the proven native-primitive builtin-conversion safe-fix subset; other repairs are manual."
810
810
  },
811
811
  {
812
812
  "task": "rule-audit/python/prefer-immutable-module-constant",
@@ -893,8 +893,8 @@
893
893
  "family": "python",
894
894
  "ruleId": "prefer-nominal-id-types",
895
895
  "state": "complete",
896
- "evidence": "Three independent reviews ran the original 73 focused cases plus precedence coverage and scanned up to 7,120 tracked Python files plus a 443-file Pygments, packaging, and pytest corpus. The original matcher produced 373 fleet findings and reproduced false positives for unlike carriers, scalar versus collection roles, shadowed primitives, unrelated UUID and wrapper types, raw TypedDict and Pydantic wire models, decorated overrides, private boundaries, SQLAlchemy Mapped fields, and operational logging payloads. Post-change validation ran 78 focused cases and 87 with precedence; the broad fleet scan fell to 199 warning candidates, a focused three-repository scan fell from 120 to 21 manually reviewed credible domain boundaries, and the popular corpus remained at zero findings. September 2026 expansion: 58 focused cases (24 positive and 34 negative, zero unexpected matches or misses) plus 17 precedence cases cover imported carriers, declared-dependency and workspace isolation, canonical non-ID roles, shadowing, suppression, and error preservation. Pinned isolated evaluation scanned 2,624 tracked Python files (21,650,669 bytes) in two private corpora with fresh processes and at most 250 files per batch. All 41 existing errors retained their locations, severity, and messages; 100 additional warnings were inspected as credible nominal-domain opportunities, with no duplicate locations or known false positives. Calibration rejected 14 earlier cross-workspace candidates: matching distribution names do not establish a shared domain. This is local consumer evidence, not fleet-wide or public-project calibration. Final rule-only baseline/candidate passes took 5.61/18.40 seconds, with peak process memory 62.3/115.6 MiB. Alternating all-rule passes over the deterministic first 250 tracked files from each corpus took 23.325/21.907 seconds for baseline and 24.710/24.577 seconds for candidate (median ratio 1.090, below the 1.25 budget); peaks were 419.8/459.8 MiB. Shared host load remains a measurement limitation. Follow-up expert type-design fifty-pass review2026-10-16: source-proven literal/domain contract gaps and inherited, runtime-factory or compiler-policy boundaries were reviewed. packages/standards/benchmarks/expert-type-design-50-passes.json records decisions, finite calibration, exact pins, robustness closures, performance scope and validation. Conservative withdrawals of legacy policy diagnostics are not counts of demonstrated runtime defects.",
897
- "outcome": "Promoted SARJ093 to error and expanded it to private, decorated, method, fake, override, and test boundaries after the motivating regressions escaped the former narrow scope. Primitive, UUID, wrapper, NewType, TypeAliasType, SQLAlchemy, Pydantic, and TypedDict decisions still require import provenance; unlike carrier shapes do not report. Generated, operational, raw-schema, SQLAlchemy Mapped, and direct Pydantic wire aliases remain excluded. Imported carrier and established non-ID coverage is staged per diagnostic as warning; shipped file-local errors, fingerprint messages, and default error metadata are unchanged. Candidate types are bounded to the owning distribution and unambiguous explicitly declared first-party dependencies, respecting nearest uv workspace members and exclusions. Canonical candidates require real typing.NewType provenance, exact role/carrier agreement, and unique production declarations. Conditional/relative imports, optional/transitive dependencies, unsupported workspace layouts, unresolved ownership, cycles, and ambiguous or mutated bindings deliberately remain unresolved. Imports are resolved only when demanded by carrier annotations or alias definitions. No autofix."
896
+ "evidence": "Three independent reviews ran the original 73 focused cases plus precedence coverage and scanned up to 7,120 tracked Python files plus a 443-file Pygments, packaging, and pytest corpus. The original matcher produced 373 fleet findings and reproduced false positives for unlike carriers, scalar versus collection roles, shadowed primitives, unrelated UUID and wrapper types, raw TypedDict and Pydantic wire models, decorated overrides, private boundaries, SQLAlchemy Mapped fields, and operational logging payloads. Post-change validation ran 78 focused cases and 87 with precedence; the broad fleet scan fell to 199 warning candidates, a focused three-repository scan fell from 120 to 21 manually reviewed credible domain boundaries, and the popular corpus remained at zero findings. September 2026 expansion: 58 focused cases (24 positive and 34 negative, zero unexpected matches or misses) plus 17 precedence cases cover imported carriers, declared-dependency and workspace isolation, canonical non-ID roles, shadowing, suppression, and error preservation. Pinned isolated evaluation scanned 2,624 tracked Python files (21,650,669 bytes) in two private corpora with fresh processes and at most 250 files per batch. All 41 existing errors retained their locations, severity, and messages; 100 additional warnings were inspected as credible nominal-domain opportunities, with no duplicate locations or known false positives. Calibration rejected 14 earlier cross-workspace candidates: matching distribution names do not establish a shared domain. This is local consumer evidence, not fleet-wide or public-project calibration. Final rule-only baseline/candidate passes took 5.61/18.40 seconds, with peak process memory 62.3/115.6 MiB. Alternating all-rule passes over the deterministic first 250 tracked files from each corpus took 23.325/21.907 seconds for baseline and 24.710/24.577 seconds for candidate (median ratio 1.090, below the 1.25 budget); peaks were 419.8/459.8 MiB. Shared host load remains a measurement limitation. Follow-up expert type-design fifty-pass review2026-10-16: source-proven literal/domain contract gaps and inherited, runtime-factory or compiler-policy boundaries were reviewed. packages/standards/benchmarks/expert-type-design-50-passes.json records decisions, finite calibration, exact pins, robustness closures, performance scope and validation. Conservative withdrawals of legacy policy diagnostics are not counts of demonstrated runtime defects. Follow-up: packages/python/benchmarks/service-contracts-and-ids-100-passes.json records 100 distinct semantic cases (39 true positives, 61 true negatives, no labeled false positives/negatives), five exact motivating blocking findings, deterministic three-trial cold/warm measurements on 296 guarded sample files, and completed local canonical gates. Private source and identifying pins remain local. Exact-head CI and broader review remain separate gates.",
897
+ "outcome": "Enforce SARJ093 at ERROR for existing two-role coverage, previously advisory imported/established-domain coverage and raw singleton IDs with a unique matching established nominal type. Preserve exact carrier and distribution/dependency ownership proof, ambiguity/shadowing/escape guards, inherited APIs, raw schemas and operational boundaries. No autofix."
898
898
  },
899
899
  {
900
900
  "task": "rule-audit/python/prefer-non-nullable-collection",
@@ -2485,8 +2485,8 @@
2485
2485
  "family": "python",
2486
2486
  "ruleId": "require-explicit-service-contract",
2487
2487
  "state": "pending",
2488
- "evidence": "Precision follow-up (2026-10-02): two independent policy/contract reviews reproduced existing Protocol, ABCMeta, abstract-declaration, value-dependency and unreachable-call misclassification. The refined rule passes 466 focused cases with SARJ071/466/467, full Python type checking, Ruff and all registered native rules on its source/tests. Generic adversarial regressions preserve services backed by stores and pools, a single operation and no substitution consumer. Private corpus evaluation is scoped separately; no fleet-wide precision claim. The pinned local-code reviewer caught a false negative where child-state assignment was mistaken for collaborator replacement; the fix preserves direct injected identity and four additional mutation regressions. The 96-case focused/combined/precedence suite passes after that correction. Follow-up 2026-10-12 additional thirty-pass campaign: Five judge rounds review strict typing and maintainability admission; bounded native WARNING tiers preserve runtime special signatures, source-visible model effects, variance/Self and frame/regex lifetime where relevant. Exact verification, corpus controls, sampling, performance and CI gate evidence is recorded in packages/python/benchmarks/error-promotion-next-30-passes.json.",
2489
- "outcome": "Retain SARJ465 as an explicitly requested proactive service-interface warning, without autofix or consumer-count gating. Reuse resolvable ABC or Protocol surfaces, including private, generic, inherited and imported aliased contracts; signatures remain the type checker responsibility. Only retained behavioral constructor collaborators and reachable public operations establish a candidate. Proven value/logging types, abstract declarations, static/class helpers and uncertain rewriting decorators/metaclasses are excluded. Structural Protocols visible only at external consumer/factory sites and dynamic aliases remain documented limits; do not manufacture a nominal duplicate or unnecessary public export. Promotion follow-up 2026-10-12: Enable the supported default at ERROR in Python 1.33.0 / TypeScript 16.8.0 / Standards 8.52.0. A retained collaborator and invoked public operations establish a service boundary whose operations lack a declared ABC or Protocol; reuse or declare a focused contract. No unsafe autofix or universal semantic-precision claim; preserve required contracts with the documented alternative or reasoned exact-code exception."
2488
+ "evidence": "Precision follow-up (2026-10-02): two independent policy/contract reviews reproduced existing Protocol, ABCMeta, abstract-declaration, value-dependency and unreachable-call misclassification. The refined rule passes 466 focused cases with SARJ071/466/467, full Python type checking, Ruff and all registered native rules on its source/tests. Generic adversarial regressions preserve services backed by stores and pools, a single operation and no substitution consumer. Private corpus evaluation is scoped separately; no fleet-wide precision claim. The pinned local-code reviewer caught a false negative where child-state assignment was mistaken for collaborator replacement; the fix preserves direct injected identity and four additional mutation regressions. The 96-case focused/combined/precedence suite passes after that correction. Follow-up 2026-10-12 additional thirty-pass campaign: Five judge rounds review strict typing and maintainability admission; bounded native WARNING tiers preserve runtime special signatures, source-visible model effects, variance/Self and frame/regex lifetime where relevant. Exact verification, corpus controls, sampling, performance and CI gate evidence is recorded in packages/python/benchmarks/error-promotion-next-30-passes.json. Follow-up: packages/python/benchmarks/service-contracts-and-ids-100-passes.json records 100 distinct semantic cases (39 true positives, 61 true negatives, no labeled false positives/negatives), five exact motivating blocking findings, deterministic three-trial cold/warm measurements on 296 guarded sample files, and completed local canonical gates. Private source and identifying pins remain local. Exact-head CI and broader review remain separate gates.",
2489
+ "outcome": "Retain SARJ465 at ERROR without autofix. Native retained-callback dispatch and per-call HTTP operations establish a service boundary regardless of Queue/Client suffixes. Reuse an ABC or Protocol that covers the operations. Preserve value/lifecycle exclusions, proven contract ancestry and unresolved/escaping ownership guards."
2490
2490
  },
2491
2491
  {
2492
2492
  "task": "rule-audit/typescript/require-explicit-service-contract",
@@ -2853,6 +2853,14 @@
2853
2853
  "state": "complete",
2854
2854
  "evidence": "Final supported-scope evaluation scans 2,830 pinned TypeScript files across nine isolated sources, capped at 250 files per fresh process with four cold/warm scans. All 74 target warnings are exhaustively inspected: 65 JSX, three dependency and six union findings, all labeled synthetic positives; zero confirmed false positives in the inspected final set and zero new real-code findings across 2,673 real files. Sixty-four ordinary-function JSX false negatives and 128 accepted explicit-forwarding sites remain recorded separately. The run has no parser failures and deterministic complete diagnostics. Its 7,440 missing-information occurrences are not unique dependencies or files and do not constitute a clean semantic scan. Generated, suppressed, incomplete, escaping, contextual and domain cases remain separate exclusions or unsupported cases. Three earlier fresh trials on 2,829 files remain historical evidence; their candidate was not qualified after an additional optional-covering-property counterexample was confirmed. The final narrower proof preserves every inspected warning tuple and accepts the separately appended regression. Exact source, corpus pins and raw evidence remain local; public reports omit private identities, source and identifying pins. Performance, full native verification, independent review and exact-head CI remain separate merge gates. Finite inspected precision is not universal absence of false positives. Native TypeScript 6.0.3 probes establish proper Dog-to-Animal coverage and independently reproduce Extract, in-narrowing and fresh-literal changes. Native assignability alone is insufficient: a covering-only optional property rejects an existing identifier, and global Object Any can supply an implicit witness. The corrected rule requires every covering member, including optional members, in the covered declared surface. Two ordinary/implicit-Any regressions and the shared erased-eval controls pass.",
2855
2855
  "outcome": "Ship the initial scope as WARNING without fixes or suggestions: an inline binary parameter union in the same proven private scalar-consumer boundary, complete readonly broad primitive object surfaces, proper one-way native assignability and all covering members explicitly present in the covered surface. Retain the covering type, never blindly the narrower subtype. Preserve public/type-level alternatives, producers, Any, unknown, generics, variance/callbacks, overloads, nominal/branded and incomplete contracts. General union simplification and Python imported-subtype approximation are withdrawn; error promotion needs a separate qualified change."
2856
+ },
2857
+ {
2858
+ "task": "rule-audit/python/prefer-grouped-settings",
2859
+ "family": "python",
2860
+ "ruleId": "prefer-grouped-settings",
2861
+ "state": "pending",
2862
+ "evidence": "Twenty-eight focused settings checks cover repeated Python field namespaces, environment-alias independence, owned and inherited fields, ClassVar and Final metadata, private fields, generated and test exclusions, imported BaseSettings ancestry, stable locations and exact suppressions. Private source, paths and identifying pins stay outside public artifacts. Follow-up: packages/python/benchmarks/service-contracts-and-ids-100-passes.json records 100 distinct semantic cases (39 true positives, 61 true negatives, no labeled false positives/negatives), five exact motivating blocking findings, deterministic three-trial cold/warm measurements on 296 guarded sample files, and completed local canonical gates. Private source and identifying pins remain local. Exact-head CI and broader review remain separate gates.",
2863
+ "outcome": "Stage SARJ532 at WARNING without autofix. At least two directly owned public BaseSettings fields must share a complete Python namespace token; environment aliases alone do not qualify. Forty-four matching groups in the private sample remain API/environment review advisories. Preserve existing loading, aliases, defaults and source precedence when grouping manually."
2856
2864
  }
2857
2865
  ]
2858
2866
  }