code-standards 8.129.9__tar.gz → 8.130.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 (206) hide show
  1. {code_standards-8.129.9 → code_standards-8.130.0}/PKG-INFO +6 -6
  2. {code_standards-8.129.9 → code_standards-8.130.0}/README.md +1 -1
  3. {code_standards-8.129.9 → code_standards-8.130.0}/pyproject.toml +5 -5
  4. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/api.py +5 -17
  5. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/cli/main.py +151 -43
  6. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/configs/cli-reference.v1.json +14 -3
  7. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/configs/eslint.peers.json +2 -2
  8. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/libs/adoption/doctor.py +2 -2
  9. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/libs/adoption/hooks.py +5 -6
  10. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/libs/adoption/lifecycle.py +82 -16
  11. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/libs/adoption/scaffold.py +1 -1
  12. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/libs/adoption/transaction.py +62 -10
  13. code_standards-8.130.0/src/sarj_standards/libs/linting/_cloudbuild_autofix.py +134 -0
  14. code_standards-8.130.0/src/sarj_standards/libs/linting/autofix.py +248 -0
  15. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/libs/linting/external.py +7 -4
  16. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/libs/linting/policy.py +9 -0
  17. code_standards-8.130.0/src/sarj_standards/libs/linting/python_fixes.py +39 -0
  18. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/libs/linting/runner.py +88 -17
  19. code_standards-8.130.0/src/sarj_standards/libs/linting/text_rules/cloudbuild_contract.py +136 -0
  20. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/libs/linting/textlint.py +219 -8
  21. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/libs/repository/docs.py +4 -2
  22. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/libs/repository/rule_examples.py +21 -4
  23. code_standards-8.130.0/src/sarj_standards/schemas/rule-catalog.v1.json +1 -0
  24. code_standards-8.129.9/src/sarj_standards/libs/linting/python_fixes.py +0 -111
  25. code_standards-8.129.9/src/sarj_standards/libs/linting/text_rules/cloudbuild_contract.py +0 -93
  26. code_standards-8.129.9/src/sarj_standards/schemas/rule-catalog.v1.json +0 -1
  27. {code_standards-8.129.9 → code_standards-8.130.0}/.gitignore +0 -0
  28. {code_standards-8.129.9 → code_standards-8.130.0}/LICENSE +0 -0
  29. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/__init__.py +0 -0
  30. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/__main__.py +0 -0
  31. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/_meta.py +0 -0
  32. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/cli/__init__.py +0 -0
  33. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/configs/Mintfile.mobile.strict +0 -0
  34. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/configs/action-parser/LICENSE.actions +0 -0
  35. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/configs/action-parser/LICENSE.cronstrue +0 -0
  36. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/configs/action-parser/LICENSE.yaml +0 -0
  37. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/configs/action-parser/generate.mts +0 -0
  38. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/configs/action-parser/index.mts +0 -0
  39. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/configs/action-parser/package-lock.json +0 -0
  40. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/configs/action-parser/package.json +0 -0
  41. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/configs/action-parser/upstream.json +0 -0
  42. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/configs/action-parser.cjs +0 -0
  43. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/configs/actionlint.strict.yaml +0 -0
  44. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/configs/basedpyright.python315-watch.json +0 -0
  45. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/configs/basedpyright.strict.json +0 -0
  46. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/configs/checkov.strict.yml +0 -0
  47. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/configs/compile-eslint.mts +0 -0
  48. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/configs/detekt.strict.yml +0 -0
  49. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/configs/devops-verification.v1.json +0 -0
  50. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/configs/doctor.config.json +0 -0
  51. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/configs/eslint-compact-formatter.mts +0 -0
  52. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/configs/eslint-required-policy.mts +0 -0
  53. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/configs/eslint-selected-rules.mts +0 -0
  54. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/configs/eslint.application.mjs +0 -0
  55. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/configs/eslint.strict.mjs +0 -0
  56. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/configs/eslint.strict.ts +0 -0
  57. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/configs/hadolint.strict.yaml +0 -0
  58. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/configs/ktlint.strict.editorconfig +0 -0
  59. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/configs/markdownlint.strict.yaml +0 -0
  60. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/configs/mobile-tools.versions.json +0 -0
  61. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/configs/mobsf.strict.yml +0 -0
  62. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/configs/pyright.strict.json +0 -0
  63. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/configs/ruff.application.toml +0 -0
  64. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/configs/ruff.cast.toml +0 -0
  65. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/configs/ruff.python315-watch.toml +0 -0
  66. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/configs/ruff.required.toml +0 -0
  67. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/configs/ruff.strict.toml +0 -0
  68. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/configs/rule-calibration-campaign.v1.json +0 -0
  69. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/configs/rule-inventory.v1.json +0 -0
  70. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/configs/rule-ledger.json +0 -0
  71. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/configs/rule-level-source.mts +0 -0
  72. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/configs/schemas/SKAFFOLD-LICENSE +0 -0
  73. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/configs/schemas/google-build-v1-schema.json +0 -0
  74. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/configs/schemas/google-build-v1.LICENSE +0 -0
  75. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/configs/schemas/skaffold-v4beta7.json +0 -0
  76. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/configs/schemas/upstream-schemas.json +0 -0
  77. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/configs/semgrep-overrides.txt +0 -0
  78. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/configs/shellcheck.strict.rc +0 -0
  79. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/configs/swiftformat.strict +0 -0
  80. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/configs/swiftlint.strict.yml +0 -0
  81. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/configs/taplo.strict.toml +0 -0
  82. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/configs/tflint.strict.hcl +0 -0
  83. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/configs/tflint.version.hcl +0 -0
  84. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/configs/tool-json.mts +0 -0
  85. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/configs/yamllint.strict.yaml +0 -0
  86. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/configs/zizmor.strict.yml +0 -0
  87. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/libs/__init__.py +0 -0
  88. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/libs/adoption/__init__.py +0 -0
  89. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/libs/adoption/age_transition.py +0 -0
  90. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/libs/adoption/configs.py +0 -0
  91. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/libs/adoption/devops.py +0 -0
  92. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/libs/adoption/exclusions.py +0 -0
  93. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/libs/adoption/launcher.py +0 -0
  94. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/libs/adoption/manifest.py +0 -0
  95. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/libs/adoption/native_bootstrap.py +0 -0
  96. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/libs/adoption/packagemanager.py +0 -0
  97. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/libs/adoption/repository_baseline.py +0 -0
  98. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/libs/adoption/retired_suppressions.py +0 -0
  99. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/libs/adoption/service.py +0 -0
  100. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/libs/adoption/upgrade.py +0 -0
  101. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/libs/adoption/uvtool.py +0 -0
  102. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/libs/catalogs/__init__.py +0 -0
  103. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/libs/catalogs/slack_automations.py +0 -0
  104. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/libs/corpus/__init__.py +0 -0
  105. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/libs/corpus/manifest.py +0 -0
  106. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/libs/corpus/snapshot.py +0 -0
  107. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/libs/diagnostics/__init__.py +0 -0
  108. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/libs/diagnostics/analysis.schema.json +0 -0
  109. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/libs/diagnostics/baseline.py +0 -0
  110. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/libs/diagnostics/models.py +0 -0
  111. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/libs/diagnostics/serialize.py +0 -0
  112. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/libs/diagnostics/source.py +0 -0
  113. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/libs/filesystem.py +0 -0
  114. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/libs/json_boundary.py +0 -0
  115. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/libs/linting/__init__.py +0 -0
  116. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/libs/linting/action_metadata.py +0 -0
  117. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/libs/linting/analysis.py +0 -0
  118. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/libs/linting/chart_schemas.py +0 -0
  119. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/libs/linting/cloudbuild.py +0 -0
  120. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/libs/linting/cloudbuild_schema.py +0 -0
  121. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/libs/linting/complexity_baseline.py +0 -0
  122. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/libs/linting/devops_programs.py +0 -0
  123. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/libs/linting/devops_schema.py +0 -0
  124. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/libs/linting/devops_source.py +0 -0
  125. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/libs/linting/devops_tools.py +0 -0
  126. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/libs/linting/duplicate_code.py +0 -0
  127. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/libs/linting/embedded_shell.py +0 -0
  128. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/libs/linting/kubernetes_context.py +0 -0
  129. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/libs/linting/library_policy.py +0 -0
  130. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/libs/linting/mobile_tools.py +0 -0
  131. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/libs/linting/prepared_devops.py +0 -0
  132. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/libs/linting/prepared_kubernetes.py +0 -0
  133. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/libs/linting/prepared_native.py +0 -0
  134. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/libs/linting/repo_standards.py +0 -0
  135. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/libs/linting/scheduling.py +0 -0
  136. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/libs/linting/security_tools.py +0 -0
  137. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/libs/linting/shell_ast.py +0 -0
  138. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/libs/linting/shell_format.py +0 -0
  139. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/libs/linting/shell_policy.py +0 -0
  140. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/libs/linting/test_value.py +0 -0
  141. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/libs/linting/text_rule_base.py +0 -0
  142. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/libs/linting/text_rules/__init__.py +0 -0
  143. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/libs/linting/text_rules/_registry.py +0 -0
  144. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/libs/linting/toml_literals.py +0 -0
  145. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/libs/linting/unused_modules.py +0 -0
  146. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/libs/release/__init__.py +0 -0
  147. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/libs/release/_values.py +0 -0
  148. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/libs/release/artifacts.py +0 -0
  149. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/libs/release/causality.py +0 -0
  150. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/libs/release/changes.py +0 -0
  151. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/libs/release/ci_artifacts.py +0 -0
  152. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/libs/release/make_checks.py +0 -0
  153. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/libs/release/metadata_verification.py +0 -0
  154. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/libs/release/native_test_setup.py +0 -0
  155. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/libs/release/process.py +0 -0
  156. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/libs/release/publish.py +0 -0
  157. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/libs/release/registry.py +0 -0
  158. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/libs/release/release_age.py +0 -0
  159. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/libs/release/release_detect.py +0 -0
  160. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/libs/release/retirement.py +0 -0
  161. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/libs/release/reviewed_analysis.py +0 -0
  162. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/libs/release/rollout.py +0 -0
  163. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/libs/release/status.py +0 -0
  164. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/libs/release/tags.py +0 -0
  165. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/libs/release/test_selection.py +0 -0
  166. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/libs/release/typescript.py +0 -0
  167. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/libs/release/verification_process.py +0 -0
  168. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/libs/release/wheel_tests.py +0 -0
  169. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/libs/repository/__init__.py +0 -0
  170. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/libs/repository/cli_reference_artifact.py +0 -0
  171. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/libs/repository/cloudbuild_schema_projection.py +0 -0
  172. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/libs/repository/comment_corpus.py +0 -0
  173. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/libs/repository/config_generation.py +0 -0
  174. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/libs/repository/hooks.py +0 -0
  175. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/libs/repository/immutable_git.py +0 -0
  176. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/libs/repository/ledger.py +0 -0
  177. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/libs/repository/repository.py +0 -0
  178. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/libs/repository/ruff_freshness.py +0 -0
  179. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/libs/repository/rule_authoring.py +0 -0
  180. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/libs/repository/rule_catalog_artifact.py +0 -0
  181. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/libs/repository/rule_changes.py +0 -0
  182. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/libs/repository/rule_checkout.py +0 -0
  183. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/libs/repository/rule_dependencies.py +0 -0
  184. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/libs/repository/rule_imports.mts +0 -0
  185. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/libs/repository/rule_inventory_artifact.py +0 -0
  186. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/libs/repository/rule_level_source.py +0 -0
  187. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/libs/repository/rule_lifecycle.py +0 -0
  188. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/libs/repository/rule_maintenance.py +0 -0
  189. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/libs/repository/rule_registration.py +0 -0
  190. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/libs/repository/shell_checks.py +0 -0
  191. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/libs/repository/third_party_catalog_artifact.py +0 -0
  192. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/libs/rules/__init__.py +0 -0
  193. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/libs/rules/catalog.py +0 -0
  194. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/libs/rules/contracts.py +0 -0
  195. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/libs/rules/corpus_runner.py +0 -0
  196. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/libs/rules/evaluation.py +0 -0
  197. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/libs/schema_boundary.py +0 -0
  198. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/libs/setup/__init__.py +0 -0
  199. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/libs/setup/repository.py +0 -0
  200. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/libs/typed_containers.py +0 -0
  201. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/libs/yaml_boundary.py +0 -0
  202. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/py.typed +0 -0
  203. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/schemas/__init__.py +0 -0
  204. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/schemas/_paths.py +0 -0
  205. {code_standards-8.129.9 → code_standards-8.130.0}/src/sarj_standards/schemas/rule-catalog.v1.schema.json +0 -0
  206. {code_standards-8.129.9 → code_standards-8.130.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.9
3
+ Version: 8.130.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.1
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.0
34
+ Requires-Dist: sarj-python-lint==1.75.0
35
+ Requires-Dist: sarj-rule-contracts==0.4.0
36
+ Requires-Dist: sarj-sql-lint==0.26.0
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.9"
3
+ version = "8.130.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.0",
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.1",
36
- "sarj-sql-lint==0.25.1",
34
+ "sarj-iac-lint==0.30.0",
35
+ "sarj-python-lint==1.75.0",
36
+ "sarj-sql-lint==0.26.0",
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.9).",
3309
- "version": "8.129.9"
3319
+ "summary": "Adopt, check, fix, diagnose, and update sarj-ai standards (v8.130.0).",
3320
+ "version": "8.130.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",
@@ -587,7 +587,7 @@ def _check_precommit_hooks(
587
587
  yield Finding(
588
588
  Level.DRIFT,
589
589
  ".pre-commit-config.yaml",
590
- "pre-commit does not run exactly one canonical `code-standards check --staged` hook",
590
+ "pre-commit does not run exactly one canonical `code-standards check --staged --fix` hook",
591
591
  "doctor.hooks.precommit",
592
592
  "run `code-standards update --offline`",
593
593
  )
@@ -634,7 +634,7 @@ def _check_lefthook_hooks(
634
634
  yield Finding(
635
635
  Level.DRIFT,
636
636
  "lefthook.yml",
637
- "Lefthook does not run exactly one unconditional `code-standards check --staged` during pre-commit",
637
+ "Lefthook does not run exactly one unconditional `code-standards check --staged --fix` during pre-commit",
638
638
  "doctor.hooks.lefthook",
639
639
  "run `code-standards update --offline`",
640
640
  )
@@ -24,9 +24,7 @@ if TYPE_CHECKING:
24
24
 
25
25
  LEFTHOOK_NAMES: Final = ("lefthook.yml", "lefthook.yaml")
26
26
  PRECOMMIT_NAMES: Final = (".pre-commit-config.yaml", ".pre-commit-config.yml")
27
- SOURCE_STAGED_COMMAND: Final = (
28
- "uv run --no-config --project packages/standards --frozen code-standards check --staged --trust-repository-code"
29
- )
27
+ SOURCE_STAGED_COMMAND: Final = "uv run --no-config --project packages/standards --frozen code-standards check --staged --fix --trust-repository-code"
30
28
  _COMMANDS_BLOCK: Final = re.compile(r"(?m)^(?P<indent> +)commands:(?P<tail>[^\n]*)$")
31
29
  _JOBS_BLOCK: Final = re.compile(r"(?m)^(?P<indent> +)jobs:(?P<tail>[^\n]*)$")
32
30
  _MAX_JOB_DEPTH: Final = 64
@@ -313,7 +311,7 @@ def precommit_runs_staged_check(root: Path) -> bool:
313
311
  candidate = candidates[0]
314
312
  return (
315
313
  candidate.get("id") == "sarj-standards-check"
316
- and candidate.get("entry") == f"{launcher.repository_command()} check --staged --trust-repository-code"
314
+ and candidate.get("entry") == f"{launcher.repository_command()} check --staged --fix --trust-repository-code"
317
315
  and candidate.get("language") == "system"
318
316
  and candidate.get("verbose") is True
319
317
  and candidate.get("always_run") is True
@@ -703,7 +701,8 @@ def _runs_staged_check(value: object) -> bool:
703
701
  tokens = shlex.split(value)
704
702
  except ValueError:
705
703
  return False
706
- source_prefix = shlex.split(SOURCE_STAGED_COMMAND)[:-1]
704
+ source_tokens = shlex.split(SOURCE_STAGED_COMMAND)
705
+ source_prefix = source_tokens[: source_tokens.index("check") + 2]
707
706
  if tokens[: len(source_prefix)] == source_prefix:
708
707
  return True
709
708
  prefix = launcher.repository_argv()
@@ -778,7 +777,7 @@ def _is_exact_standards_argv(tokens: list[str]) -> bool:
778
777
  def canonical_staged_command(root: Path | None = None) -> str:
779
778
  if root is not None and (root / "packages" / "standards" / "pyproject.toml").is_file():
780
779
  return SOURCE_STAGED_COMMAND
781
- return f"{launcher.repository_command()} check --staged --trust-repository-code"
780
+ return f"{launcher.repository_command()} check --staged --fix --trust-repository-code"
782
781
 
783
782
 
784
783
  def _canonical_commit_message_command(root: Path | None = None, *, runner_prefix: str | None = None) -> str: