code-standards 8.56.1__tar.gz → 8.58.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.
- {code_standards-8.56.1 → code_standards-8.58.0}/PKG-INFO +6 -2
- {code_standards-8.56.1 → code_standards-8.58.0}/README.md +4 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/pyproject.toml +2 -2
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/api.py +48 -14
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/cli/main.py +109 -35
- code_standards-8.58.0/src/sarj_standards/configs/cli-reference.v1.json +1 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/configs/eslint-selected-rules.mjs +4 -2
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/configs/rule-calibration-campaign.v1.json +8 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/configs/rule-inventory.v1.json +1 -1
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/configs/rule-ledger.json +3 -1
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/libs/adoption/doctor.py +2 -4
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/libs/adoption/hooks.py +133 -37
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/libs/adoption/lifecycle.py +2 -2
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/libs/adoption/scaffold.py +3 -3
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/libs/linting/analysis.py +4 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/libs/linting/external.py +2 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/libs/linting/runner.py +8 -2
- code_standards-8.58.0/src/sarj_standards/libs/linting/test_value.py +37 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/libs/repository/docs.py +11 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/libs/repository/hooks.py +56 -2
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/schemas/rule-catalog.v1.json +1 -1
- code_standards-8.56.1/src/sarj_standards/configs/cli-reference.v1.json +0 -1
- {code_standards-8.56.1 → code_standards-8.58.0}/.gitignore +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/LICENSE +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/__init__.py +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/__main__.py +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/_meta.py +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/cli/__init__.py +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/configs/Mintfile.mobile.strict +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/configs/actionlint.strict.yaml +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/configs/basedpyright.python315-watch.json +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/configs/basedpyright.strict.json +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/configs/checkov.strict.yml +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/configs/detekt.strict.yml +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/configs/devops-verification.v1.json +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/configs/doctor.config.json +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/configs/eslint-compact-formatter.mjs +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/configs/eslint.application.mjs +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/configs/eslint.peers.json +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/configs/eslint.strict.mjs +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/configs/hadolint.strict.yaml +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/configs/ktlint.strict.editorconfig +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/configs/markdownlint.strict.yaml +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/configs/mobile-tools.versions.json +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/configs/mobsf.strict.yml +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/configs/pyright.strict.json +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/configs/ruff.application.toml +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/configs/ruff.python315-watch.toml +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/configs/ruff.strict.toml +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/configs/rule-level-source.mjs +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/configs/schemas/SKAFFOLD-LICENSE +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/configs/schemas/skaffold-v4beta7.json +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/configs/schemas/upstream-schemas.json +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/configs/semgrep-overrides.txt +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/configs/shellcheck.strict.rc +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/configs/swiftformat.strict +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/configs/swiftlint.strict.yml +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/configs/taplo.strict.toml +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/configs/tflint.strict.hcl +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/configs/tflint.version.hcl +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/configs/yamllint.strict.yaml +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/configs/zizmor.strict.yml +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/libs/__init__.py +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/libs/adoption/__init__.py +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/libs/adoption/age_transition.py +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/libs/adoption/configs.py +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/libs/adoption/devops.py +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/libs/adoption/exclusions.py +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/libs/adoption/launcher.py +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/libs/adoption/manifest.py +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/libs/adoption/native_bootstrap.py +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/libs/adoption/packagemanager.py +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/libs/adoption/repository_baseline.py +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/libs/adoption/retired_suppressions.py +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/libs/adoption/service.py +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/libs/adoption/transaction.py +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/libs/adoption/upgrade.py +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/libs/adoption/uvtool.py +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/libs/catalogs/__init__.py +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/libs/catalogs/slack_automations.py +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/libs/corpus/__init__.py +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/libs/corpus/manifest.py +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/libs/corpus/snapshot.py +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/libs/diagnostics/__init__.py +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/libs/diagnostics/analysis.schema.json +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/libs/diagnostics/baseline.py +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/libs/diagnostics/models.py +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/libs/diagnostics/serialize.py +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/libs/diagnostics/source.py +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/libs/filesystem.py +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/libs/json_boundary.py +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/libs/linting/__init__.py +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/libs/linting/chart_schemas.py +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/libs/linting/cloudbuild.py +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/libs/linting/devops_programs.py +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/libs/linting/devops_schema.py +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/libs/linting/devops_source.py +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/libs/linting/devops_tools.py +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/libs/linting/duplicate_code.py +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/libs/linting/embedded_shell.py +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/libs/linting/kubernetes_context.py +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/libs/linting/library_policy.py +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/libs/linting/mobile_tools.py +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/libs/linting/policy.py +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/libs/linting/prepared_devops.py +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/libs/linting/prepared_kubernetes.py +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/libs/linting/repo_standards.py +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/libs/linting/scheduling.py +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/libs/linting/security_tools.py +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/libs/linting/shell_ast.py +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/libs/linting/shell_format.py +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/libs/linting/shell_policy.py +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/libs/linting/text_rule_base.py +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/libs/linting/text_rules/__init__.py +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/libs/linting/text_rules/_registry.py +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/libs/linting/text_rules/cloudbuild_contract.py +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/libs/linting/textlint.py +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/libs/linting/toml_literals.py +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/libs/linting/unused_modules.py +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/libs/release/__init__.py +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/libs/release/_values.py +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/libs/release/artifacts.py +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/libs/release/causality.py +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/libs/release/changes.py +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/libs/release/ci_artifacts.py +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/libs/release/make_checks.py +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/libs/release/metadata_verification.py +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/libs/release/native_test_setup.py +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/libs/release/process.py +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/libs/release/publish.py +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/libs/release/registry.py +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/libs/release/release_age.py +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/libs/release/release_detect.py +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/libs/release/retirement.py +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/libs/release/reviewed_analysis.py +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/libs/release/rollout.py +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/libs/release/status.py +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/libs/release/tags.py +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/libs/release/test_selection.py +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/libs/release/typescript.py +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/libs/release/verification_process.py +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/libs/release/wheel_tests.py +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/libs/repository/__init__.py +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/libs/repository/cli_reference_artifact.py +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/libs/repository/comment_corpus.py +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/libs/repository/config_generation.py +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/libs/repository/immutable_git.py +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/libs/repository/ledger.py +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/libs/repository/repository.py +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/libs/repository/ruff_freshness.py +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/libs/repository/rule_authoring.py +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/libs/repository/rule_catalog_artifact.py +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/libs/repository/rule_changes.py +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/libs/repository/rule_checkout.py +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/libs/repository/rule_dependencies.py +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/libs/repository/rule_examples.py +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/libs/repository/rule_imports.cjs +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/libs/repository/rule_inventory_artifact.py +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/libs/repository/rule_level_source.py +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/libs/repository/rule_lifecycle.py +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/libs/repository/rule_maintenance.py +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/libs/repository/rule_registration.py +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/libs/repository/shell_checks.py +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/libs/repository/third_party_catalog_artifact.py +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/libs/rules/__init__.py +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/libs/rules/catalog.py +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/libs/rules/contracts.py +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/libs/rules/corpus_runner.py +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/libs/rules/evaluation.py +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/libs/schema_boundary.py +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/libs/setup/__init__.py +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/libs/setup/repository.py +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/libs/typed_containers.py +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/libs/yaml_boundary.py +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/py.typed +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/schemas/__init__.py +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/schemas/_paths.py +0 -0
- {code_standards-8.56.1 → code_standards-8.58.0}/src/sarj_standards/schemas/rule-catalog.v1.schema.json +0 -0
- {code_standards-8.56.1 → code_standards-8.58.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.
|
|
3
|
+
Version: 8.58.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/
|
|
@@ -31,7 +31,7 @@ Requires-Dist: referencing==0.37.0
|
|
|
31
31
|
Requires-Dist: repo-standards==6.6.0
|
|
32
32
|
Requires-Dist: ruff==0.17.0
|
|
33
33
|
Requires-Dist: sarj-iac-lint==0.21.0
|
|
34
|
-
Requires-Dist: sarj-python-lint==1.
|
|
34
|
+
Requires-Dist: sarj-python-lint==1.37.0
|
|
35
35
|
Requires-Dist: sarj-rule-contracts==0.2.4
|
|
36
36
|
Requires-Dist: sarj-sql-lint==0.20.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')
|
|
@@ -50,6 +50,10 @@ 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.
|
|
54
|
+
|
|
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
|
+
|
|
53
57
|
```bash
|
|
54
58
|
code-standards setup
|
|
55
59
|
code-standards check
|
|
@@ -10,6 +10,10 @@ 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.
|
|
14
|
+
|
|
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
|
+
|
|
13
17
|
```bash
|
|
14
18
|
code-standards setup
|
|
15
19
|
code-standards check
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "code-standards"
|
|
3
|
-
version = "8.
|
|
3
|
+
version = "8.58.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"
|
|
@@ -32,7 +32,7 @@ dependencies = [
|
|
|
32
32
|
"ruff==0.17.0",
|
|
33
33
|
"shellcheck-py==0.11.0.1; (sys_platform == 'darwin' and platform_machine == 'arm64') or (sys_platform == 'darwin' and platform_machine == 'x86_64') or (sys_platform == 'linux' and platform_machine == 'x86_64') or (sys_platform == 'win32' and platform_machine == 'AMD64')",
|
|
34
34
|
"sarj-iac-lint==0.21.0",
|
|
35
|
-
"sarj-python-lint==1.
|
|
35
|
+
"sarj-python-lint==1.37.0",
|
|
36
36
|
"sarj-sql-lint==0.20.0",
|
|
37
37
|
"typer==0.27.3",
|
|
38
38
|
]
|
|
@@ -54,7 +54,7 @@ from .libs.diagnostics import (
|
|
|
54
54
|
)
|
|
55
55
|
from .libs.filesystem import is_link_like
|
|
56
56
|
from .libs.linting.analysis import analyze as analyze_paths, report_from_tools
|
|
57
|
-
from .libs.linting.external import analyze_external
|
|
57
|
+
from .libs.linting.external import UpstreamESLintRules, analyze_external
|
|
58
58
|
from .libs.linting.library_policy import (
|
|
59
59
|
ManifestPolicyError,
|
|
60
60
|
accepts_path as library_policy_accepts_path,
|
|
@@ -78,6 +78,7 @@ if TYPE_CHECKING:
|
|
|
78
78
|
|
|
79
79
|
_INVALID_EXIT = 2
|
|
80
80
|
_INTERRUPTED_EXIT = 130
|
|
81
|
+
_NO_UPSTREAM_ESLINT_RULES = UpstreamESLintRules()
|
|
81
82
|
_INVALID_DOCTOR_FINDING_IDS = frozenset(
|
|
82
83
|
{"doctor.manifest.destination", "doctor.config.unknown", "doctor.package-json.invalid"}
|
|
83
84
|
)
|
|
@@ -250,6 +251,7 @@ class Standards:
|
|
|
250
251
|
trust: TrustMode | str = TrustMode.SAFE,
|
|
251
252
|
mode: AnalysisMode | str = AnalysisMode.POLICY,
|
|
252
253
|
rules: Sequence[str | RuleSelector] | None = None,
|
|
254
|
+
upstream_rules: UpstreamESLintRules = _NO_UPSTREAM_ESLINT_RULES,
|
|
253
255
|
staged: bool = False,
|
|
254
256
|
react_doctor_triggered: bool = False,
|
|
255
257
|
include_react_doctor: bool = True,
|
|
@@ -262,6 +264,7 @@ class Standards:
|
|
|
262
264
|
) -> AnalysisReport:
|
|
263
265
|
if jobs not in {1, 2}:
|
|
264
266
|
return _failed_analysis(self.root, "invalid-input", "analysis jobs must be 1 or 2")
|
|
267
|
+
external = external or bool(upstream_rules.ids)
|
|
265
268
|
try:
|
|
266
269
|
normalized_trust = TrustMode(trust)
|
|
267
270
|
normalized_mode = AnalysisMode(mode)
|
|
@@ -291,10 +294,7 @@ class Standards:
|
|
|
291
294
|
selected_groups = group_paths(active_selected, policy=selection_policy)
|
|
292
295
|
except (OSError, TypeError, ValueError) as exc:
|
|
293
296
|
return _failed_analysis(self.root, "invalid-input", str(exc))
|
|
294
|
-
|
|
295
|
-
react_doctor_full_scan = not staged and (
|
|
296
|
-
requested_paths is None or any(Path(path) == Path() for path in requested_paths)
|
|
297
|
-
)
|
|
297
|
+
react_doctor_full_scan = _react_doctor_full_scan(adopted, paths, staged=staged)
|
|
298
298
|
|
|
299
299
|
def native_analysis() -> tuple[ToolReport, ...]:
|
|
300
300
|
native = analyze_paths(
|
|
@@ -311,7 +311,9 @@ class Standards:
|
|
|
311
311
|
prepared = _prepared_reports(self.root, adopted, prepared_devops, prepared_targets)
|
|
312
312
|
return (*native.tools, *prepared)
|
|
313
313
|
|
|
314
|
-
coverage = _selection_coverage(
|
|
314
|
+
coverage = _selection_coverage(
|
|
315
|
+
self.root, selected, active_selected, selected_groups, rule_selection, upstream_rules=upstream_rules
|
|
316
|
+
)
|
|
315
317
|
coverage.extend(_prepared_coverage(adopted, prepared_devops))
|
|
316
318
|
if not external:
|
|
317
319
|
native = report_from_tools(self.root, native_analysis())
|
|
@@ -355,14 +357,18 @@ class Standards:
|
|
|
355
357
|
react_doctor_full_scan=react_doctor_full_scan,
|
|
356
358
|
pass_on_unpruned_eslint_suppressions=pass_on_unpruned_eslint_suppressions,
|
|
357
359
|
python_type_check=python_type_check,
|
|
360
|
+
upstream_rules=upstream_rules,
|
|
358
361
|
)
|
|
359
362
|
|
|
360
363
|
combined = report_from_tools(
|
|
361
364
|
self.root, analyze_groups(self.root, native_analysis, external_analysis, jobs=jobs)
|
|
362
365
|
)
|
|
363
366
|
combined = _with_shell_format_severity(combined, paths=paths, staged=staged, changed_scope=changed_scope)
|
|
364
|
-
|
|
365
|
-
combined
|
|
367
|
+
combined = _with_warning_severity(
|
|
368
|
+
combined,
|
|
369
|
+
_warning_rule_keys() if normalized_mode in {AnalysisMode.POLICY, AnalysisMode.OBSERVE} else frozenset(),
|
|
370
|
+
upstream_rules=upstream_rules,
|
|
371
|
+
)
|
|
366
372
|
return _with_coverage(
|
|
367
373
|
_without_baselined_diagnostics(combined, baseline_counts, changed_scope=changed_scope), coverage
|
|
368
374
|
)
|
|
@@ -717,6 +723,7 @@ def _selected_external_analysis(
|
|
|
717
723
|
react_doctor_full_scan: bool,
|
|
718
724
|
pass_on_unpruned_eslint_suppressions: bool,
|
|
719
725
|
python_type_check: bool,
|
|
726
|
+
upstream_rules: UpstreamESLintRules,
|
|
720
727
|
) -> tuple[ToolReport, ...]:
|
|
721
728
|
rule_ids = (
|
|
722
729
|
frozenset(str(value) for value in rule_selection.ids_for(RuleEngine.ESLINT))
|
|
@@ -724,12 +731,13 @@ def _selected_external_analysis(
|
|
|
724
731
|
else None
|
|
725
732
|
)
|
|
726
733
|
external_engines = frozenset({RuleEngine.ESLINT, RuleEngine.CHECKOV, RuleEngine.ZIZMOR})
|
|
734
|
+
upstream_capabilities = frozenset({"eslint"}) if upstream_rules.ids else frozenset[str]()
|
|
727
735
|
selected_capabilities = (
|
|
728
|
-
frozenset(engine.value for engine in rule_selection.engines & external_engines)
|
|
736
|
+
frozenset(engine.value for engine in rule_selection.engines & external_engines) | upstream_capabilities
|
|
729
737
|
if rule_selection is not None
|
|
730
738
|
else None
|
|
731
739
|
)
|
|
732
|
-
run_external =
|
|
740
|
+
run_external = selected_capabilities is None or bool(selected_capabilities)
|
|
733
741
|
external_reports = (
|
|
734
742
|
(
|
|
735
743
|
analyze_external(
|
|
@@ -742,6 +750,7 @@ def _selected_external_analysis(
|
|
|
742
750
|
),
|
|
743
751
|
grouped=selected_groups,
|
|
744
752
|
rule_ids=rule_ids,
|
|
753
|
+
upstream_rules=upstream_rules,
|
|
745
754
|
security_selection=rule_selection,
|
|
746
755
|
include_react_doctor=include_react_doctor and rule_selection is None,
|
|
747
756
|
force_react_doctor=react_doctor_triggered,
|
|
@@ -758,6 +767,7 @@ def _selected_external_analysis(
|
|
|
758
767
|
capabilities=selected_capabilities,
|
|
759
768
|
grouped=selected_groups,
|
|
760
769
|
rule_ids=rule_ids,
|
|
770
|
+
upstream_rules=upstream_rules,
|
|
761
771
|
security_selection=rule_selection,
|
|
762
772
|
include_react_doctor=include_react_doctor and rule_selection is None,
|
|
763
773
|
force_react_doctor=react_doctor_triggered,
|
|
@@ -771,7 +781,10 @@ def _selected_external_analysis(
|
|
|
771
781
|
else ()
|
|
772
782
|
)
|
|
773
783
|
if rule_selection is not None:
|
|
774
|
-
external_reports = tuple(
|
|
784
|
+
external_reports = tuple(
|
|
785
|
+
_filter_report_selectors(report, rule_selection, upstream_rules=upstream_rules)
|
|
786
|
+
for report in external_reports
|
|
787
|
+
)
|
|
775
788
|
return external_reports
|
|
776
789
|
|
|
777
790
|
|
|
@@ -805,12 +818,19 @@ def _with_repository_analysis(root: Path, native: AnalysisReport, *, staged: boo
|
|
|
805
818
|
return native
|
|
806
819
|
|
|
807
820
|
|
|
821
|
+
def _react_doctor_full_scan(adopted: Manifest | None, paths: Sequence[str] | None, *, staged: bool) -> bool:
|
|
822
|
+
requested_paths = adopted.verify_paths if paths is None and adopted is not None else paths
|
|
823
|
+
return not staged and (requested_paths is None or any(Path(path) == Path() for path in requested_paths))
|
|
824
|
+
|
|
825
|
+
|
|
808
826
|
def _selection_coverage(
|
|
809
827
|
root: Path,
|
|
810
828
|
selected: list[str],
|
|
811
829
|
active_selected: list[str],
|
|
812
830
|
selected_groups: GroupedPaths,
|
|
813
831
|
rule_selection: RuleSelection | None,
|
|
832
|
+
*,
|
|
833
|
+
upstream_rules: UpstreamESLintRules,
|
|
814
834
|
) -> list[CoverageNotice]:
|
|
815
835
|
coverage: list[CoverageNotice] = []
|
|
816
836
|
excluded = sum(Path(item).is_file() and item not in active_selected for item in selected)
|
|
@@ -824,6 +844,8 @@ def _selection_coverage(
|
|
|
824
844
|
)
|
|
825
845
|
)
|
|
826
846
|
routed = _routed_for_selection(selected_groups, rule_selection)
|
|
847
|
+
if upstream_rules.ids:
|
|
848
|
+
routed.update(selected_groups.typescript)
|
|
827
849
|
if rule_selection is None:
|
|
828
850
|
routed.update(
|
|
829
851
|
item for item in active_selected if Path(item).is_file() and library_policy_accepts_path(Path(item), root)
|
|
@@ -941,9 +963,13 @@ def _routed_for_selection(grouped: object, selected: RuleSelection | None) -> se
|
|
|
941
963
|
def _filter_report_selectors(
|
|
942
964
|
report: ToolReport,
|
|
943
965
|
selected: RuleSelection,
|
|
966
|
+
*,
|
|
967
|
+
upstream_rules: UpstreamESLintRules = _NO_UPSTREAM_ESLINT_RULES,
|
|
944
968
|
) -> ToolReport:
|
|
945
969
|
engine = RuleEngine(report.name) if report.name in {"eslint", "zizmor", "checkov"} else None
|
|
946
970
|
allowed: frozenset[str] = frozenset() if engine is None else selected.native_ids_for(engine)
|
|
971
|
+
if engine is RuleEngine.ESLINT:
|
|
972
|
+
allowed |= upstream_rules.ids
|
|
947
973
|
return ToolReport(
|
|
948
974
|
report.name,
|
|
949
975
|
report.completion,
|
|
@@ -966,15 +992,23 @@ def _warning_rule_keys() -> frozenset[RuleSelector]:
|
|
|
966
992
|
return warning_selectors()
|
|
967
993
|
|
|
968
994
|
|
|
969
|
-
def _with_warning_severity(
|
|
970
|
-
|
|
995
|
+
def _with_warning_severity(
|
|
996
|
+
report: AnalysisReport,
|
|
997
|
+
selectors: frozenset[RuleSelector],
|
|
998
|
+
*,
|
|
999
|
+
upstream_rules: UpstreamESLintRules = _NO_UPSTREAM_ESLINT_RULES,
|
|
1000
|
+
) -> AnalysisReport:
|
|
1001
|
+
if not selectors and not upstream_rules.warning_only:
|
|
971
1002
|
return report
|
|
972
1003
|
tools = tuple(
|
|
973
1004
|
ToolReport(
|
|
974
1005
|
tool.name,
|
|
975
1006
|
tool.completion,
|
|
976
1007
|
diagnostics=tuple(
|
|
977
|
-
replace(item, severity=Severity.WARNING)
|
|
1008
|
+
replace(item, severity=Severity.WARNING)
|
|
1009
|
+
if _selector_for_diagnostic(item) in selectors
|
|
1010
|
+
or (tool.name == "eslint" and upstream_rules.warning_only and item.rule_id in upstream_rules.ids)
|
|
1011
|
+
else item
|
|
978
1012
|
for item in tool.diagnostics
|
|
979
1013
|
),
|
|
980
1014
|
issues=tool.issues,
|
|
@@ -180,6 +180,8 @@ class _Args:
|
|
|
180
180
|
ratchet_cmd: str = ""
|
|
181
181
|
baseline_cmd: str = ""
|
|
182
182
|
selected_rules: list[RuleSelector] = field(default_factory=list)
|
|
183
|
+
test_value: bool = False
|
|
184
|
+
observation_base: str | None = None
|
|
183
185
|
corpus_manifest: Path | None = None
|
|
184
186
|
private_overlay: Path | None = None
|
|
185
187
|
selector: RuleSelector | None = None
|
|
@@ -1128,15 +1130,6 @@ def cmd_check(args: _Args) -> int:
|
|
|
1128
1130
|
if health_status:
|
|
1129
1131
|
return health_status
|
|
1130
1132
|
args.files = [path for path in args.files if runner.accepts_hook_path(Path(path), root=root)]
|
|
1131
|
-
if not args.files and not scope.react_doctor_triggered:
|
|
1132
|
-
return _run_canonical_check(
|
|
1133
|
-
root,
|
|
1134
|
-
(),
|
|
1135
|
-
trusted=args.trust_repository_code,
|
|
1136
|
-
staged=True,
|
|
1137
|
-
jobs=args.jobs,
|
|
1138
|
-
python_type_check=args.python_type_check,
|
|
1139
|
-
)
|
|
1140
1133
|
if args.output_format != "text":
|
|
1141
1134
|
return _check_machine_output(args, root, scope)
|
|
1142
1135
|
return _check_text_output(args, root, scope)
|
|
@@ -1160,6 +1153,11 @@ def _check_selected_rules(args: _Args, root: Path, scope: _CheckScope) -> int:
|
|
|
1160
1153
|
|
|
1161
1154
|
|
|
1162
1155
|
def _check_text_output(args: _Args, root: Path, scope: _CheckScope) -> int:
|
|
1156
|
+
if args.staged and not args.files:
|
|
1157
|
+
check_options: dict[str, bool] = {"trusted": args.trust_repository_code, "staged": True}
|
|
1158
|
+
if scope.react_doctor_triggered:
|
|
1159
|
+
check_options["react_doctor_triggered"] = True
|
|
1160
|
+
return _run_canonical_check(root, (), jobs=args.jobs, python_type_check=args.python_type_check, **check_options)
|
|
1163
1161
|
if scope.pull_request_scoped:
|
|
1164
1162
|
adoption_report = _machine_adoption_gate(root)
|
|
1165
1163
|
if adoption_report is not None:
|
|
@@ -1183,7 +1181,7 @@ def _check_text_output(args: _Args, root: Path, scope: _CheckScope) -> int:
|
|
|
1183
1181
|
)
|
|
1184
1182
|
if not args.files:
|
|
1185
1183
|
return cmd_verify(args)
|
|
1186
|
-
check_options
|
|
1184
|
+
check_options = {
|
|
1187
1185
|
"trusted": args.trust_repository_code,
|
|
1188
1186
|
"staged": args.staged,
|
|
1189
1187
|
}
|
|
@@ -1286,11 +1284,11 @@ def _check_machine_output(args: _Args, root: Path, scope: _CheckScope) -> int:
|
|
|
1286
1284
|
args.external = True
|
|
1287
1285
|
args.trust = "trusted" if args.trust_repository_code else "safe"
|
|
1288
1286
|
args.analysis_mode = "policy"
|
|
1289
|
-
if scope.repository_wide:
|
|
1287
|
+
if scope.repository_wide and not args.staged:
|
|
1290
1288
|
adoption_report = _machine_adoption_gate(root)
|
|
1291
1289
|
if adoption_report is not None:
|
|
1292
1290
|
return _emit_analysis_report(args, root, adoption_report)
|
|
1293
|
-
if scope.pull_request_scoped and not args.files:
|
|
1291
|
+
if (scope.pull_request_scoped or args.staged) and not args.files:
|
|
1294
1292
|
from sarj_standards.api import ( # ruff: ignore[import-outside-top-level]
|
|
1295
1293
|
AnalysisMode,
|
|
1296
1294
|
Standards,
|
|
@@ -1303,6 +1301,7 @@ def _check_machine_output(args: _Args, root: Path, scope: _CheckScope) -> int:
|
|
|
1303
1301
|
jobs=args.jobs,
|
|
1304
1302
|
trust=TrustMode.TRUSTED if args.trust_repository_code else TrustMode.SAFE,
|
|
1305
1303
|
mode=AnalysisMode.POLICY,
|
|
1304
|
+
staged=args.staged,
|
|
1306
1305
|
react_doctor_triggered=scope.react_doctor_triggered,
|
|
1307
1306
|
python_type_check=args.python_type_check,
|
|
1308
1307
|
)
|
|
@@ -1400,6 +1399,11 @@ def _run_canonical_check(
|
|
|
1400
1399
|
rendered = to_text(report)
|
|
1401
1400
|
if rendered:
|
|
1402
1401
|
print(rendered, end="" if rendered.endswith("\n") else "\n")
|
|
1402
|
+
if staged and report.diagnostics:
|
|
1403
|
+
print(
|
|
1404
|
+
"Agent: address the findings above. Run `code-standards fix --staged` for safe mechanical fixes, "
|
|
1405
|
+
"review the changes, stage the intended edits, and retry the commit."
|
|
1406
|
+
)
|
|
1403
1407
|
return report.exit_code
|
|
1404
1408
|
|
|
1405
1409
|
|
|
@@ -1613,32 +1617,75 @@ def _object_table(value: object) -> dict[str, object] | None:
|
|
|
1613
1617
|
|
|
1614
1618
|
def cmd_observe(args: _Args) -> int:
|
|
1615
1619
|
from sarj_standards.api import AnalysisMode, Standards, TrustMode # ruff: ignore[import-outside-top-level]
|
|
1616
|
-
from sarj_standards.libs.linting.
|
|
1620
|
+
from sarj_standards.libs.linting.external import UpstreamESLintRules # ruff: ignore[import-outside-top-level]
|
|
1621
|
+
from sarj_standards.libs.linting.test_value import UPSTREAM_RULES # ruff: ignore[import-outside-top-level]
|
|
1617
1622
|
|
|
1618
1623
|
root = _resolve_dest(args.dest)
|
|
1619
1624
|
if _validate_analysis_output(args, root):
|
|
1620
1625
|
return 2
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
print(
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
|
|
1626
|
+
try:
|
|
1627
|
+
selected_rules = _observation_rules(args)
|
|
1628
|
+
files = _observation_paths(args, root)
|
|
1629
|
+
except (OSError, ValueError, subprocess.SubprocessError) as exc:
|
|
1630
|
+
print(f"error: {exc}", file=sys.stderr)
|
|
1631
|
+
return _emit_analysis_report(args, root, _machine_input_error(root, str(exc)))
|
|
1632
|
+
if files == []:
|
|
1633
|
+
from sarj_standards.libs.diagnostics import ( # ruff: ignore[import-outside-top-level]
|
|
1634
|
+
AnalysisReport,
|
|
1635
|
+
Completion,
|
|
1636
|
+
Conclusion,
|
|
1629
1637
|
)
|
|
1630
|
-
|
|
1638
|
+
|
|
1639
|
+
return _emit_analysis_report(args, root, AnalysisReport(root, Completion.COMPLETE, Conclusion.PASSED, ()))
|
|
1631
1640
|
report = Standards(root).analyze(
|
|
1632
|
-
|
|
1641
|
+
files,
|
|
1633
1642
|
jobs=args.jobs,
|
|
1634
|
-
external=any(selector.engine.value == "eslint" for selector in
|
|
1643
|
+
external=args.test_value or any(selector.engine.value == "eslint" for selector in selected_rules),
|
|
1635
1644
|
trust=TrustMode.TRUSTED if args.trust_repository_code else TrustMode.SAFE,
|
|
1636
1645
|
mode=AnalysisMode.OBSERVE,
|
|
1637
|
-
rules=
|
|
1646
|
+
rules=selected_rules,
|
|
1647
|
+
upstream_rules=UpstreamESLintRules(UPSTREAM_RULES, warning_only=True)
|
|
1648
|
+
if args.test_value
|
|
1649
|
+
else UpstreamESLintRules(),
|
|
1638
1650
|
)
|
|
1639
1651
|
return _emit_analysis_report(args, root, report)
|
|
1640
1652
|
|
|
1641
1653
|
|
|
1654
|
+
def _observation_rules(args: _Args) -> list[RuleSelector]:
|
|
1655
|
+
from sarj_standards.libs.linting.policy import warning_selectors # ruff: ignore[import-outside-top-level]
|
|
1656
|
+
from sarj_standards.libs.linting.test_value import SELECTORS # ruff: ignore[import-outside-top-level]
|
|
1657
|
+
|
|
1658
|
+
warning_rules = warning_selectors()
|
|
1659
|
+
selected_rules = sorted(set(args.selected_rules) | (SELECTORS if args.test_value else frozenset()), key=str)
|
|
1660
|
+
if not selected_rules:
|
|
1661
|
+
msg = "observe requires --rule or --test-value"
|
|
1662
|
+
raise ValueError(msg)
|
|
1663
|
+
invalid = sorted(set(selected_rules) - warning_rules)
|
|
1664
|
+
if invalid:
|
|
1665
|
+
rendered = ", ".join(map(str, invalid))
|
|
1666
|
+
msg = (
|
|
1667
|
+
f"observe accepts warning-stage rules only: {rendered}; "
|
|
1668
|
+
f"next: code-standards maintain rules stage-warning {invalid[0]}"
|
|
1669
|
+
)
|
|
1670
|
+
raise ValueError(msg)
|
|
1671
|
+
return selected_rules
|
|
1672
|
+
|
|
1673
|
+
|
|
1674
|
+
def _observation_paths(args: _Args, root: Path) -> list[str] | None:
|
|
1675
|
+
from sarj_standards.libs.linting.test_value import select_test_paths # ruff: ignore[import-outside-top-level]
|
|
1676
|
+
|
|
1677
|
+
files = args.files or None
|
|
1678
|
+
if args.observation_base is not None:
|
|
1679
|
+
if args.files:
|
|
1680
|
+
msg = "observe --base cannot be combined with explicit paths"
|
|
1681
|
+
raise ValueError(msg)
|
|
1682
|
+
files = _changed_file_paths(root, args.observation_base)
|
|
1683
|
+
if args.test_value:
|
|
1684
|
+
candidates = _selected_paths(root, files) if files is not None else _selected_paths(root, ["."])
|
|
1685
|
+
return select_test_paths(root, candidates)
|
|
1686
|
+
return files
|
|
1687
|
+
|
|
1688
|
+
|
|
1642
1689
|
def _rule_evaluation_summary(report: object, selectors: Sequence[RuleSelector]) -> str:
|
|
1643
1690
|
from sarj_standards.libs.diagnostics import AnalysisReport # ruff: ignore[import-outside-top-level]
|
|
1644
1691
|
from sarj_standards.libs.rules import RuleEngine # ruff: ignore[import-outside-top-level]
|
|
@@ -2000,7 +2047,7 @@ def _staged_file_names(root: Path) -> list[str]:
|
|
|
2000
2047
|
msg = "git is required for --staged"
|
|
2001
2048
|
raise OSError(msg)
|
|
2002
2049
|
completed = subprocess.run( # ruff: ignore[subprocess-without-shell-equals-true] -- fixed argv, no shell.
|
|
2003
|
-
[git, "diff", "--cached", "--name-only", "
|
|
2050
|
+
[git, "diff", "--cached", "--name-only", "-z"],
|
|
2004
2051
|
cwd=root,
|
|
2005
2052
|
check=True,
|
|
2006
2053
|
capture_output=True,
|
|
@@ -2150,11 +2197,9 @@ def cmd_format(args: _Args) -> int:
|
|
|
2150
2197
|
print("fix: run `code-standards doctor --repair`, then retry", file=sys.stderr)
|
|
2151
2198
|
return 2 if any(finding.id in _INVALID_DOCTOR_IDS for finding in drifted) else 1
|
|
2152
2199
|
if args.staged:
|
|
2153
|
-
|
|
2154
|
-
|
|
2155
|
-
|
|
2156
|
-
print(f"error: cannot read staged files: {exc}", file=sys.stderr)
|
|
2157
|
-
return 2
|
|
2200
|
+
selection_status = _select_staged_fix(args, root)
|
|
2201
|
+
if selection_status is not None:
|
|
2202
|
+
return selection_status
|
|
2158
2203
|
elif args.files:
|
|
2159
2204
|
try:
|
|
2160
2205
|
args.files = _selected_paths(root, args.files)
|
|
@@ -2171,6 +2216,27 @@ def cmd_format(args: _Args) -> int:
|
|
|
2171
2216
|
return lifecycle.execute(commands)
|
|
2172
2217
|
|
|
2173
2218
|
|
|
2219
|
+
def _select_staged_fix(args: _Args, root: Path) -> int | None:
|
|
2220
|
+
try:
|
|
2221
|
+
staged_names = _staged_file_names(root)
|
|
2222
|
+
drifted = _unstaged_versions(root, staged_names)
|
|
2223
|
+
if drifted:
|
|
2224
|
+
print(
|
|
2225
|
+
"error: --staged found files with unstaged content; stage the intended versions before fixing: "
|
|
2226
|
+
+ ", ".join(drifted),
|
|
2227
|
+
file=sys.stderr,
|
|
2228
|
+
)
|
|
2229
|
+
return 2
|
|
2230
|
+
args.files = _safe_staged_paths(root, staged_names)
|
|
2231
|
+
except (OSError, subprocess.SubprocessError) as exc:
|
|
2232
|
+
print(f"error: cannot read staged files: {exc}", file=sys.stderr)
|
|
2233
|
+
return 2
|
|
2234
|
+
if not args.files:
|
|
2235
|
+
print("No staged files to fix.")
|
|
2236
|
+
return 0
|
|
2237
|
+
return None
|
|
2238
|
+
|
|
2239
|
+
|
|
2174
2240
|
def _staged_files(root: Path) -> list[str]:
|
|
2175
2241
|
return _safe_staged_paths(root, _staged_file_names(root))
|
|
2176
2242
|
|
|
@@ -3043,7 +3109,7 @@ def build_app(handler: Callable[[_Args], int] = _dispatch) -> typer.Typer:
|
|
|
3043
3109
|
bool,
|
|
3044
3110
|
typer.Option(
|
|
3045
3111
|
"--staged",
|
|
3046
|
-
help="run
|
|
3112
|
+
help="run the complete gate on staged files; optional paths narrow the staged selection",
|
|
3047
3113
|
),
|
|
3048
3114
|
] = False,
|
|
3049
3115
|
selected_rules: Annotated[
|
|
@@ -3094,9 +3160,15 @@ def build_app(handler: Callable[[_Args], int] = _dispatch) -> typer.Typer:
|
|
|
3094
3160
|
ctx: typer.Context,
|
|
3095
3161
|
*,
|
|
3096
3162
|
selected_rules: Annotated[
|
|
3097
|
-
list[RuleSelector],
|
|
3163
|
+
list[RuleSelector] | None,
|
|
3098
3164
|
typer.Option("--rule", parser=_parse_rule_selector, help="canonical ENGINE:ID selector (repeatable)"),
|
|
3099
|
-
],
|
|
3165
|
+
] = None,
|
|
3166
|
+
test_value: Annotated[
|
|
3167
|
+
bool, typer.Option("--test-value", help="report the curated opt-in test-oracle advisories")
|
|
3168
|
+
] = False,
|
|
3169
|
+
base: Annotated[
|
|
3170
|
+
str | None, typer.Option("--base", help="observe existing paths changed from this Git base")
|
|
3171
|
+
] = None,
|
|
3100
3172
|
output_format: Annotated[_DiagnosticFormat, typer.Option("--format")] = _DiagnosticFormat.TEXT,
|
|
3101
3173
|
output: Annotated[Path | None, typer.Option("--output")] = None,
|
|
3102
3174
|
trust_repository_code: Annotated[
|
|
@@ -3112,7 +3184,9 @@ def build_app(handler: Callable[[_Args], int] = _dispatch) -> typer.Typer:
|
|
|
3112
3184
|
_Args(
|
|
3113
3185
|
dest=_command_root(ctx),
|
|
3114
3186
|
cmd="observe",
|
|
3115
|
-
selected_rules=selected_rules,
|
|
3187
|
+
selected_rules=selected_rules or [],
|
|
3188
|
+
test_value=test_value,
|
|
3189
|
+
observation_base=base,
|
|
3116
3190
|
output_format=output_format.value,
|
|
3117
3191
|
output=output if output is not None else None,
|
|
3118
3192
|
trust_repository_code=trust_repository_code,
|