code-standards 8.12.1__tar.gz → 8.13.1__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.12.1 → code_standards-8.13.1}/PKG-INFO +8 -6
- code_standards-8.13.1/README.md +28 -0
- {code_standards-8.12.1 → code_standards-8.13.1}/pyproject.toml +11 -5
- {code_standards-8.12.1 → code_standards-8.13.1}/src/sarj_standards/api.py +25 -5
- {code_standards-8.12.1 → code_standards-8.13.1}/src/sarj_standards/cli/main.py +2 -0
- code_standards-8.13.1/src/sarj_standards/configs/checkov.strict.yml +15 -0
- code_standards-8.13.1/src/sarj_standards/configs/cli-reference.v1.json +1 -0
- code_standards-8.13.1/src/sarj_standards/configs/zizmor.strict.yml +2 -0
- {code_standards-8.12.1 → code_standards-8.13.1}/src/sarj_standards/libs/adoption/configs.py +2 -0
- {code_standards-8.12.1 → code_standards-8.13.1}/src/sarj_standards/libs/adoption/doctor.py +2 -0
- {code_standards-8.12.1 → code_standards-8.13.1}/src/sarj_standards/libs/adoption/lifecycle.py +7 -1
- {code_standards-8.12.1 → code_standards-8.13.1}/src/sarj_standards/libs/adoption/manifest.py +44 -18
- {code_standards-8.12.1 → code_standards-8.13.1}/src/sarj_standards/libs/adoption/scaffold.py +40 -2
- {code_standards-8.12.1 → code_standards-8.13.1}/src/sarj_standards/libs/adoption/service.py +1 -1
- {code_standards-8.12.1 → code_standards-8.13.1}/src/sarj_standards/libs/adoption/upgrade.py +15 -3
- {code_standards-8.12.1 → code_standards-8.13.1}/src/sarj_standards/libs/linting/external.py +128 -1
- {code_standards-8.12.1 → code_standards-8.13.1}/src/sarj_standards/libs/linting/runner.py +3 -2
- code_standards-8.13.1/src/sarj_standards/libs/linting/security_tools.py +477 -0
- {code_standards-8.12.1 → code_standards-8.13.1}/src/sarj_standards/libs/linting/textlint.py +132 -5
- {code_standards-8.12.1 → code_standards-8.13.1}/src/sarj_standards/libs/repository/docs.py +10 -2
- {code_standards-8.12.1 → code_standards-8.13.1}/src/sarj_standards/libs/repository/repository.py +2 -0
- {code_standards-8.12.1 → code_standards-8.13.1}/src/sarj_standards/libs/repository/third_party_catalog_artifact.py +95 -16
- code_standards-8.13.1/src/sarj_standards/schemas/rule-catalog.v1.json +1 -0
- code_standards-8.12.1/README.md +0 -26
- code_standards-8.12.1/src/sarj_standards/configs/cli-reference.v1.json +0 -1
- code_standards-8.12.1/src/sarj_standards/schemas/rule-catalog.v1.json +0 -1
- {code_standards-8.12.1 → code_standards-8.13.1}/.gitignore +0 -0
- {code_standards-8.12.1 → code_standards-8.13.1}/LICENSE +0 -0
- {code_standards-8.12.1 → code_standards-8.13.1}/src/sarj_standards/__init__.py +0 -0
- {code_standards-8.12.1 → code_standards-8.13.1}/src/sarj_standards/__main__.py +0 -0
- {code_standards-8.12.1 → code_standards-8.13.1}/src/sarj_standards/_meta.py +0 -0
- {code_standards-8.12.1 → code_standards-8.13.1}/src/sarj_standards/cli/__init__.py +0 -0
- {code_standards-8.12.1 → code_standards-8.13.1}/src/sarj_standards/configs/Mintfile.mobile.strict +0 -0
- {code_standards-8.12.1 → code_standards-8.13.1}/src/sarj_standards/configs/basedpyright.python315-watch.json +0 -0
- {code_standards-8.12.1 → code_standards-8.13.1}/src/sarj_standards/configs/basedpyright.strict.json +0 -0
- {code_standards-8.12.1 → code_standards-8.13.1}/src/sarj_standards/configs/detekt.strict.yml +0 -0
- {code_standards-8.12.1 → code_standards-8.13.1}/src/sarj_standards/configs/doctor.config.json +0 -0
- {code_standards-8.12.1 → code_standards-8.13.1}/src/sarj_standards/configs/eslint-compact-formatter.mjs +0 -0
- {code_standards-8.12.1 → code_standards-8.13.1}/src/sarj_standards/configs/eslint-selected-rules.mjs +0 -0
- {code_standards-8.12.1 → code_standards-8.13.1}/src/sarj_standards/configs/eslint.application.mjs +0 -0
- {code_standards-8.12.1 → code_standards-8.13.1}/src/sarj_standards/configs/eslint.peers.json +0 -0
- {code_standards-8.12.1 → code_standards-8.13.1}/src/sarj_standards/configs/eslint.strict.mjs +0 -0
- {code_standards-8.12.1 → code_standards-8.13.1}/src/sarj_standards/configs/ktlint.strict.editorconfig +0 -0
- {code_standards-8.12.1 → code_standards-8.13.1}/src/sarj_standards/configs/markdownlint.strict.yaml +0 -0
- {code_standards-8.12.1 → code_standards-8.13.1}/src/sarj_standards/configs/mobile-tools.versions.json +0 -0
- {code_standards-8.12.1 → code_standards-8.13.1}/src/sarj_standards/configs/mobsf.strict.yml +0 -0
- {code_standards-8.12.1 → code_standards-8.13.1}/src/sarj_standards/configs/pyright.strict.json +0 -0
- {code_standards-8.12.1 → code_standards-8.13.1}/src/sarj_standards/configs/ruff.application.toml +0 -0
- {code_standards-8.12.1 → code_standards-8.13.1}/src/sarj_standards/configs/ruff.python315-watch.toml +0 -0
- {code_standards-8.12.1 → code_standards-8.13.1}/src/sarj_standards/configs/ruff.strict.toml +0 -0
- {code_standards-8.12.1 → code_standards-8.13.1}/src/sarj_standards/configs/rule-calibration-campaign.v1.json +0 -0
- {code_standards-8.12.1 → code_standards-8.13.1}/src/sarj_standards/configs/rule-inventory.v1.json +0 -0
- {code_standards-8.12.1 → code_standards-8.13.1}/src/sarj_standards/configs/rule-ledger.json +0 -0
- {code_standards-8.12.1 → code_standards-8.13.1}/src/sarj_standards/configs/rule-level-source.mjs +0 -0
- {code_standards-8.12.1 → code_standards-8.13.1}/src/sarj_standards/configs/shellcheck.strict.rc +0 -0
- {code_standards-8.12.1 → code_standards-8.13.1}/src/sarj_standards/configs/swiftformat.strict +0 -0
- {code_standards-8.12.1 → code_standards-8.13.1}/src/sarj_standards/configs/swiftlint.strict.yml +0 -0
- {code_standards-8.12.1 → code_standards-8.13.1}/src/sarj_standards/configs/taplo.strict.toml +0 -0
- {code_standards-8.12.1 → code_standards-8.13.1}/src/sarj_standards/configs/yamllint.strict.yaml +0 -0
- {code_standards-8.12.1 → code_standards-8.13.1}/src/sarj_standards/libs/__init__.py +0 -0
- {code_standards-8.12.1 → code_standards-8.13.1}/src/sarj_standards/libs/adoption/__init__.py +0 -0
- {code_standards-8.12.1 → code_standards-8.13.1}/src/sarj_standards/libs/adoption/age_transition.py +0 -0
- {code_standards-8.12.1 → code_standards-8.13.1}/src/sarj_standards/libs/adoption/exclusions.py +0 -0
- {code_standards-8.12.1 → code_standards-8.13.1}/src/sarj_standards/libs/adoption/hooks.py +0 -0
- {code_standards-8.12.1 → code_standards-8.13.1}/src/sarj_standards/libs/adoption/launcher.py +0 -0
- {code_standards-8.12.1 → code_standards-8.13.1}/src/sarj_standards/libs/adoption/packagemanager.py +0 -0
- {code_standards-8.12.1 → code_standards-8.13.1}/src/sarj_standards/libs/adoption/retired_suppressions.py +0 -0
- {code_standards-8.12.1 → code_standards-8.13.1}/src/sarj_standards/libs/adoption/transaction.py +0 -0
- {code_standards-8.12.1 → code_standards-8.13.1}/src/sarj_standards/libs/adoption/uvtool.py +0 -0
- {code_standards-8.12.1 → code_standards-8.13.1}/src/sarj_standards/libs/catalogs/__init__.py +0 -0
- {code_standards-8.12.1 → code_standards-8.13.1}/src/sarj_standards/libs/catalogs/slack_automations.py +0 -0
- {code_standards-8.12.1 → code_standards-8.13.1}/src/sarj_standards/libs/corpus/__init__.py +0 -0
- {code_standards-8.12.1 → code_standards-8.13.1}/src/sarj_standards/libs/corpus/manifest.py +0 -0
- {code_standards-8.12.1 → code_standards-8.13.1}/src/sarj_standards/libs/corpus/snapshot.py +0 -0
- {code_standards-8.12.1 → code_standards-8.13.1}/src/sarj_standards/libs/diagnostics/__init__.py +0 -0
- {code_standards-8.12.1 → code_standards-8.13.1}/src/sarj_standards/libs/diagnostics/analysis.schema.json +0 -0
- {code_standards-8.12.1 → code_standards-8.13.1}/src/sarj_standards/libs/diagnostics/baseline.py +0 -0
- {code_standards-8.12.1 → code_standards-8.13.1}/src/sarj_standards/libs/diagnostics/models.py +0 -0
- {code_standards-8.12.1 → code_standards-8.13.1}/src/sarj_standards/libs/diagnostics/serialize.py +0 -0
- {code_standards-8.12.1 → code_standards-8.13.1}/src/sarj_standards/libs/diagnostics/source.py +0 -0
- {code_standards-8.12.1 → code_standards-8.13.1}/src/sarj_standards/libs/filesystem.py +0 -0
- {code_standards-8.12.1 → code_standards-8.13.1}/src/sarj_standards/libs/json_boundary.py +0 -0
- {code_standards-8.12.1 → code_standards-8.13.1}/src/sarj_standards/libs/linting/__init__.py +0 -0
- {code_standards-8.12.1 → code_standards-8.13.1}/src/sarj_standards/libs/linting/analysis.py +0 -0
- {code_standards-8.12.1 → code_standards-8.13.1}/src/sarj_standards/libs/linting/library_policy.py +0 -0
- {code_standards-8.12.1 → code_standards-8.13.1}/src/sarj_standards/libs/linting/mobile_tools.py +0 -0
- {code_standards-8.12.1 → code_standards-8.13.1}/src/sarj_standards/libs/linting/policy.py +0 -0
- {code_standards-8.12.1 → code_standards-8.13.1}/src/sarj_standards/libs/linting/repo_standards.py +0 -0
- {code_standards-8.12.1 → code_standards-8.13.1}/src/sarj_standards/libs/linting/scheduling.py +0 -0
- {code_standards-8.12.1 → code_standards-8.13.1}/src/sarj_standards/libs/linting/text_rule_base.py +0 -0
- {code_standards-8.12.1 → code_standards-8.13.1}/src/sarj_standards/libs/linting/text_rules/__init__.py +0 -0
- {code_standards-8.12.1 → code_standards-8.13.1}/src/sarj_standards/libs/linting/text_rules/_registry.py +0 -0
- {code_standards-8.12.1 → code_standards-8.13.1}/src/sarj_standards/libs/release/__init__.py +0 -0
- {code_standards-8.12.1 → code_standards-8.13.1}/src/sarj_standards/libs/release/_values.py +0 -0
- {code_standards-8.12.1 → code_standards-8.13.1}/src/sarj_standards/libs/release/artifacts.py +0 -0
- {code_standards-8.12.1 → code_standards-8.13.1}/src/sarj_standards/libs/release/causality.py +0 -0
- {code_standards-8.12.1 → code_standards-8.13.1}/src/sarj_standards/libs/release/changes.py +0 -0
- {code_standards-8.12.1 → code_standards-8.13.1}/src/sarj_standards/libs/release/process.py +0 -0
- {code_standards-8.12.1 → code_standards-8.13.1}/src/sarj_standards/libs/release/publish.py +0 -0
- {code_standards-8.12.1 → code_standards-8.13.1}/src/sarj_standards/libs/release/registry.py +0 -0
- {code_standards-8.12.1 → code_standards-8.13.1}/src/sarj_standards/libs/release/release_age.py +0 -0
- {code_standards-8.12.1 → code_standards-8.13.1}/src/sarj_standards/libs/release/retirement.py +0 -0
- {code_standards-8.12.1 → code_standards-8.13.1}/src/sarj_standards/libs/release/rollout.py +0 -0
- {code_standards-8.12.1 → code_standards-8.13.1}/src/sarj_standards/libs/release/tags.py +0 -0
- {code_standards-8.12.1 → code_standards-8.13.1}/src/sarj_standards/libs/release/typescript.py +0 -0
- {code_standards-8.12.1 → code_standards-8.13.1}/src/sarj_standards/libs/repository/__init__.py +0 -0
- {code_standards-8.12.1 → code_standards-8.13.1}/src/sarj_standards/libs/repository/cli_reference_artifact.py +0 -0
- {code_standards-8.12.1 → code_standards-8.13.1}/src/sarj_standards/libs/repository/comment_corpus.py +0 -0
- {code_standards-8.12.1 → code_standards-8.13.1}/src/sarj_standards/libs/repository/config_generation.py +0 -0
- {code_standards-8.12.1 → code_standards-8.13.1}/src/sarj_standards/libs/repository/hooks.py +0 -0
- {code_standards-8.12.1 → code_standards-8.13.1}/src/sarj_standards/libs/repository/ledger.py +0 -0
- {code_standards-8.12.1 → code_standards-8.13.1}/src/sarj_standards/libs/repository/ruff_freshness.py +0 -0
- {code_standards-8.12.1 → code_standards-8.13.1}/src/sarj_standards/libs/repository/rule_authoring.py +0 -0
- {code_standards-8.12.1 → code_standards-8.13.1}/src/sarj_standards/libs/repository/rule_catalog_artifact.py +0 -0
- {code_standards-8.12.1 → code_standards-8.13.1}/src/sarj_standards/libs/repository/rule_changes.py +0 -0
- {code_standards-8.12.1 → code_standards-8.13.1}/src/sarj_standards/libs/repository/rule_checkout.py +0 -0
- {code_standards-8.12.1 → code_standards-8.13.1}/src/sarj_standards/libs/repository/rule_examples.py +0 -0
- {code_standards-8.12.1 → code_standards-8.13.1}/src/sarj_standards/libs/repository/rule_inventory_artifact.py +0 -0
- {code_standards-8.12.1 → code_standards-8.13.1}/src/sarj_standards/libs/repository/rule_level_source.py +0 -0
- {code_standards-8.12.1 → code_standards-8.13.1}/src/sarj_standards/libs/repository/rule_lifecycle.py +0 -0
- {code_standards-8.12.1 → code_standards-8.13.1}/src/sarj_standards/libs/repository/rule_maintenance.py +0 -0
- {code_standards-8.12.1 → code_standards-8.13.1}/src/sarj_standards/libs/repository/rule_registration.py +0 -0
- {code_standards-8.12.1 → code_standards-8.13.1}/src/sarj_standards/libs/rules/__init__.py +0 -0
- {code_standards-8.12.1 → code_standards-8.13.1}/src/sarj_standards/libs/rules/catalog.py +0 -0
- {code_standards-8.12.1 → code_standards-8.13.1}/src/sarj_standards/libs/rules/contracts.py +0 -0
- {code_standards-8.12.1 → code_standards-8.13.1}/src/sarj_standards/libs/rules/corpus_runner.py +0 -0
- {code_standards-8.12.1 → code_standards-8.13.1}/src/sarj_standards/libs/rules/evaluation.py +0 -0
- {code_standards-8.12.1 → code_standards-8.13.1}/src/sarj_standards/libs/setup/__init__.py +0 -0
- {code_standards-8.12.1 → code_standards-8.13.1}/src/sarj_standards/libs/setup/repository.py +0 -0
- {code_standards-8.12.1 → code_standards-8.13.1}/src/sarj_standards/libs/typed_containers.py +0 -0
- {code_standards-8.12.1 → code_standards-8.13.1}/src/sarj_standards/libs/yaml_boundary.py +0 -0
- {code_standards-8.12.1 → code_standards-8.13.1}/src/sarj_standards/py.typed +0 -0
- {code_standards-8.12.1 → code_standards-8.13.1}/src/sarj_standards/schemas/__init__.py +0 -0
- {code_standards-8.12.1 → code_standards-8.13.1}/src/sarj_standards/schemas/_paths.py +0 -0
- {code_standards-8.12.1 → code_standards-8.13.1}/src/sarj_standards/schemas/rule-catalog.v1.schema.json +0 -0
- {code_standards-8.12.1 → code_standards-8.13.1}/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.13.1
|
|
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/
|
|
@@ -27,10 +27,10 @@ Requires-Dist: pydantic==2.13.5
|
|
|
27
27
|
Requires-Dist: pyyaml==6.0.3
|
|
28
28
|
Requires-Dist: repo-standards==6.2.0
|
|
29
29
|
Requires-Dist: ruff==0.16.9
|
|
30
|
-
Requires-Dist: sarj-iac-lint==0.
|
|
31
|
-
Requires-Dist: sarj-python-lint==1.8.
|
|
32
|
-
Requires-Dist: sarj-rule-contracts==0.
|
|
33
|
-
Requires-Dist: sarj-sql-lint==0.18.
|
|
30
|
+
Requires-Dist: sarj-iac-lint==0.17.0
|
|
31
|
+
Requires-Dist: sarj-python-lint==1.8.2
|
|
32
|
+
Requires-Dist: sarj-rule-contracts==0.2.0
|
|
33
|
+
Requires-Dist: sarj-sql-lint==0.18.4
|
|
34
34
|
Requires-Dist: semgrep==1.178.0
|
|
35
35
|
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')
|
|
36
36
|
Requires-Dist: typer==0.27.2
|
|
@@ -57,7 +57,9 @@ code-standards doctor
|
|
|
57
57
|
code-standards update
|
|
58
58
|
```
|
|
59
59
|
|
|
60
|
-
Use repeatable `check --rule ENGINE:ID` selectors to
|
|
60
|
+
Use repeatable `check --rule ENGINE:ID` selectors to select native rules, ESLint rules, or managed security audits. Exclusions, baselines, and severities still apply; Ruff selectors are not supported. Native linters and ESLint execute only selected rules. ESLint retains configured parsers, options, severities, and suppression directives.
|
|
61
|
+
|
|
62
|
+
Terraform, Kubernetes, and GitHub Actions adoption adds isolated Checkov 3.3.20 and zizmor 1.30.1 runtimes. Setup and generated CI prewarm these tools; checks run offline with packaged policy. Use `--rule checkov:CKV_GCP_95` or `--rule zizmor:template-injection` to select upstream audits. Their findings start as warnings, use the canonical diagnostic baseline, and retain upstream IDs. Checkov honors its inline suppression directives; zizmor ignore comments are disabled. Explicit zizmor selectors include auditor-persona checks; online-only audits cannot run offline. Parsing or execution failures leave the analysis incomplete. Image digest evidence for source templates is deferred to their rendered deployment artifacts.
|
|
61
63
|
|
|
62
64
|
`check --jobs 2` overlaps native analysis with the external-tool pipeline. The default is `--jobs 1`; external tools remain sequential and report ordering is deterministic.
|
|
63
65
|
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
<!-- Generated by `code-standards maintain docs sync`; do not edit. -->
|
|
2
|
+
|
|
3
|
+
# code-standards
|
|
4
|
+
|
|
5
|
+
One deterministic quality gate for Sarj Python, TypeScript, Swift, Kotlin, shell, SQL, IaC, and repository policy.
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
uv tool install --python 3.14 code-standards
|
|
9
|
+
```
|
|
10
|
+
|
|
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
|
+
|
|
13
|
+
```bash
|
|
14
|
+
code-standards setup
|
|
15
|
+
code-standards check
|
|
16
|
+
code-standards check --rule python:no-excessive-cognitive-complexity src/
|
|
17
|
+
code-standards fix
|
|
18
|
+
code-standards doctor
|
|
19
|
+
code-standards update
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
Use repeatable `check --rule ENGINE:ID` selectors to select native rules, ESLint rules, or managed security audits. Exclusions, baselines, and severities still apply; Ruff selectors are not supported. Native linters and ESLint execute only selected rules. ESLint retains configured parsers, options, severities, and suppression directives.
|
|
23
|
+
|
|
24
|
+
Terraform, Kubernetes, and GitHub Actions adoption adds isolated Checkov 3.3.20 and zizmor 1.30.1 runtimes. Setup and generated CI prewarm these tools; checks run offline with packaged policy. Use `--rule checkov:CKV_GCP_95` or `--rule zizmor:template-injection` to select upstream audits. Their findings start as warnings, use the canonical diagnostic baseline, and retain upstream IDs. Checkov honors its inline suppression directives; zizmor ignore comments are disabled. Explicit zizmor selectors include auditor-persona checks; online-only audits cannot run offline. Parsing or execution failures leave the analysis incomplete. Image digest evidence for source templates is deferred to their rendered deployment artifacts.
|
|
25
|
+
|
|
26
|
+
`check --jobs 2` overlaps native analysis with the external-tool pipeline. The default is `--jobs 1`; external tools remain sequential and report ordering is deterministic.
|
|
27
|
+
|
|
28
|
+
[Documentation](https://code-standards.sarj.ai/) · [Source](https://github.com/sarj-ai/code-standards)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "code-standards"
|
|
3
|
-
version = "8.
|
|
3
|
+
version = "8.13.1"
|
|
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"
|
|
@@ -16,7 +16,7 @@ classifiers = [
|
|
|
16
16
|
"Topic :: Software Development :: Quality Assurance",
|
|
17
17
|
]
|
|
18
18
|
dependencies = [
|
|
19
|
-
"sarj-rule-contracts==0.
|
|
19
|
+
"sarj-rule-contracts==0.2.0",
|
|
20
20
|
"pathspec==1.1.1",
|
|
21
21
|
"basedpyright==1.40.1",
|
|
22
22
|
"deptry==0.25.1",
|
|
@@ -29,9 +29,9 @@ dependencies = [
|
|
|
29
29
|
"ruff==0.16.9",
|
|
30
30
|
"semgrep==1.178.0",
|
|
31
31
|
"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')",
|
|
32
|
-
"sarj-iac-lint==0.
|
|
33
|
-
"sarj-python-lint==1.8.
|
|
34
|
-
"sarj-sql-lint==0.18.
|
|
32
|
+
"sarj-iac-lint==0.17.0",
|
|
33
|
+
"sarj-python-lint==1.8.2",
|
|
34
|
+
"sarj-sql-lint==0.18.4",
|
|
35
35
|
"typer==0.27.2",
|
|
36
36
|
]
|
|
37
37
|
|
|
@@ -66,6 +66,12 @@ dev = [
|
|
|
66
66
|
"jsonschema==4.25.1",
|
|
67
67
|
"pytest>=9.1.1",
|
|
68
68
|
]
|
|
69
|
+
|
|
70
|
+
[tool.uv]
|
|
71
|
+
# Semgrep 1.178.0 requires vulnerable PyJWT 2.13.x. Remove this override when
|
|
72
|
+
# its upstream requirement admits the patched version.
|
|
73
|
+
override-dependencies = ["pyjwt[crypto]==2.15.1"]
|
|
74
|
+
|
|
69
75
|
[tool.uv.sources]
|
|
70
76
|
sarj-rule-contracts = { path = "../contracts", editable = true }
|
|
71
77
|
# Development uses the sibling packages while wheel smoke tests resolve the
|
|
@@ -635,7 +635,13 @@ def _selected_external_analysis(
|
|
|
635
635
|
if rule_selection is not None
|
|
636
636
|
else None
|
|
637
637
|
)
|
|
638
|
-
|
|
638
|
+
external_engines = frozenset({RuleEngine.ESLINT, RuleEngine.CHECKOV, RuleEngine.ZIZMOR})
|
|
639
|
+
selected_capabilities = (
|
|
640
|
+
frozenset(engine.value for engine in rule_selection.engines & external_engines)
|
|
641
|
+
if rule_selection is not None
|
|
642
|
+
else None
|
|
643
|
+
)
|
|
644
|
+
run_external = rule_selection is None or not rule_selection.engines.isdisjoint(external_engines)
|
|
639
645
|
external_reports = (
|
|
640
646
|
(
|
|
641
647
|
analyze_external(
|
|
@@ -644,10 +650,11 @@ def _selected_external_analysis(
|
|
|
644
650
|
trust=normalized_trust,
|
|
645
651
|
policy=selection_policy,
|
|
646
652
|
capabilities=(
|
|
647
|
-
|
|
653
|
+
selected_capabilities if rule_selection is not None else frozenset(adopted.enabled_capabilities)
|
|
648
654
|
),
|
|
649
655
|
grouped=selected_groups,
|
|
650
656
|
rule_ids=rule_ids,
|
|
657
|
+
security_selection=rule_selection,
|
|
651
658
|
include_react_doctor=include_react_doctor and rule_selection is None,
|
|
652
659
|
force_react_doctor=react_doctor_triggered,
|
|
653
660
|
react_doctor_staged=staged,
|
|
@@ -660,9 +667,10 @@ def _selected_external_analysis(
|
|
|
660
667
|
active_selected,
|
|
661
668
|
root=root,
|
|
662
669
|
trust=normalized_trust,
|
|
663
|
-
capabilities=
|
|
670
|
+
capabilities=selected_capabilities,
|
|
664
671
|
grouped=selected_groups,
|
|
665
672
|
rule_ids=rule_ids,
|
|
673
|
+
security_selection=rule_selection,
|
|
666
674
|
include_react_doctor=include_react_doctor and rule_selection is None,
|
|
667
675
|
force_react_doctor=react_doctor_triggered,
|
|
668
676
|
react_doctor_staged=staged,
|
|
@@ -671,7 +679,7 @@ def _selected_external_analysis(
|
|
|
671
679
|
python_type_check=python_type_check,
|
|
672
680
|
)
|
|
673
681
|
)
|
|
674
|
-
if
|
|
682
|
+
if run_external
|
|
675
683
|
else ()
|
|
676
684
|
)
|
|
677
685
|
if rule_selection is not None:
|
|
@@ -785,6 +793,9 @@ def _rule_selection(values: Sequence[str | RuleSelector] | None) -> RuleSelectio
|
|
|
785
793
|
if isinstance(values, str):
|
|
786
794
|
msg = "rules must be a sequence of canonical selectors, not one string"
|
|
787
795
|
raise TypeError(msg)
|
|
796
|
+
from sarj_standards.libs.linting import ( # ruff: ignore[import-outside-top-level] -- load the upstream selectors with the catalog.
|
|
797
|
+
security_tools,
|
|
798
|
+
)
|
|
788
799
|
from sarj_standards.libs.repository import ( # ruff: ignore[import-outside-top-level]
|
|
789
800
|
rule_catalog_artifact,
|
|
790
801
|
)
|
|
@@ -792,6 +803,8 @@ def _rule_selection(values: Sequence[str | RuleSelector] | None) -> RuleSelectio
|
|
|
792
803
|
catalog = rule_catalog_artifact.load()
|
|
793
804
|
raw_rules = _object_list(catalog.get("rules"), "shipped rule catalog rules")
|
|
794
805
|
live: set[RuleSelector] = set()
|
|
806
|
+
live.update(RuleSelector(RuleEngine.CHECKOV, RuleId(rule)) for rule in security_tools.CHECKOV_CHECKS)
|
|
807
|
+
live.update(RuleSelector(RuleEngine.ZIZMOR, RuleId(rule)) for rule in security_tools.ZIZMOR_RULES)
|
|
795
808
|
for value in raw_rules:
|
|
796
809
|
key = value.get("key") if is_object_mapping(value) else None
|
|
797
810
|
if isinstance(key, str):
|
|
@@ -799,6 +812,9 @@ def _rule_selection(values: Sequence[str | RuleSelector] | None) -> RuleSelectio
|
|
|
799
812
|
selected: set[RuleSelector] = set()
|
|
800
813
|
for value in values:
|
|
801
814
|
selector = value if isinstance(value, RuleSelector) else RuleSelector.parse(value)
|
|
815
|
+
if selector.engine is RuleEngine.ZIZMOR and selector.rule_id in security_tools.ZIZMOR_ONLINE_ONLY:
|
|
816
|
+
msg = f"{selector} cannot run in offline analysis; choose an offline audit"
|
|
817
|
+
raise ValueError(msg)
|
|
802
818
|
if selector not in live:
|
|
803
819
|
msg = f"unknown or invalid rule selector: {value}"
|
|
804
820
|
raise ValueError(msg)
|
|
@@ -822,6 +838,8 @@ def _routed_for_selection(grouped: object, selected: RuleSelection | None) -> se
|
|
|
822
838
|
routed.update(grouped.sql)
|
|
823
839
|
if RuleEngine.IAC in engines:
|
|
824
840
|
routed.update(grouped.iac)
|
|
841
|
+
if not engines.isdisjoint({RuleEngine.CHECKOV, RuleEngine.ZIZMOR}):
|
|
842
|
+
routed.update(grouped.iac)
|
|
825
843
|
if RuleEngine.TEXT in engines:
|
|
826
844
|
routed.update(grouped.text)
|
|
827
845
|
if RuleEngine.ESLINT in engines:
|
|
@@ -836,7 +854,7 @@ def _filter_report_selectors(
|
|
|
836
854
|
report: ToolReport,
|
|
837
855
|
selected: RuleSelection,
|
|
838
856
|
) -> ToolReport:
|
|
839
|
-
engine = RuleEngine.
|
|
857
|
+
engine = RuleEngine(report.name) if report.name in {"eslint", "zizmor", "checkov"} else None
|
|
840
858
|
allowed: frozenset[str] = frozenset() if engine is None else selected.native_ids_for(engine)
|
|
841
859
|
return ToolReport(
|
|
842
860
|
report.name,
|
|
@@ -908,6 +926,8 @@ def _engine_for_diagnostic(item: Diagnostic) -> RuleEngine | None:
|
|
|
908
926
|
"iac": RuleEngine.IAC,
|
|
909
927
|
"text": RuleEngine.TEXT,
|
|
910
928
|
"eslint": RuleEngine.ESLINT,
|
|
929
|
+
"checkov": RuleEngine.CHECKOV,
|
|
930
|
+
"zizmor": RuleEngine.ZIZMOR,
|
|
911
931
|
}.get(item.source)
|
|
912
932
|
|
|
913
933
|
|
|
@@ -2628,6 +2628,7 @@ class _ProfileChoice(StrEnum):
|
|
|
2628
2628
|
|
|
2629
2629
|
|
|
2630
2630
|
class _ConfigChoice(StrEnum):
|
|
2631
|
+
CHECKOV = "checkov"
|
|
2631
2632
|
DETEKT = "detekt"
|
|
2632
2633
|
ESLINT = "eslint"
|
|
2633
2634
|
KTLINT = "ktlint"
|
|
@@ -2640,6 +2641,7 @@ class _ConfigChoice(StrEnum):
|
|
|
2640
2641
|
SWIFTLINT = "swiftlint"
|
|
2641
2642
|
TAPLO = "taplo"
|
|
2642
2643
|
YAMLLINT = "yamllint"
|
|
2644
|
+
ZIZMOR = "zizmor"
|
|
2643
2645
|
|
|
2644
2646
|
|
|
2645
2647
|
class _DiagnosticFormat(StrEnum):
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# Checkov is isolated from the Standards runtime and never downloads modules.
|
|
2
|
+
framework:
|
|
3
|
+
- terraform
|
|
4
|
+
- kubernetes
|
|
5
|
+
check:
|
|
6
|
+
- CKV_GCP_41
|
|
7
|
+
- CKV_GCP_95
|
|
8
|
+
- CKV_GCP_97
|
|
9
|
+
- CKV_K8S_10
|
|
10
|
+
- CKV_K8S_12
|
|
11
|
+
- CKV_K8S_13
|
|
12
|
+
- CKV_K8S_43
|
|
13
|
+
download-external-modules: false
|
|
14
|
+
skip-download: true
|
|
15
|
+
output: json
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"commands":[{"commands":[],"name":"commit-message","options":[{"choices":[],"kind":"option","metavar":null,"names":["-h","--help"],"repeatable":false,"required":false,"summary":"Show this message and exit."},{"choices":[],"kind":"positional","metavar":"COMMIT_MSG_FILE","names":["message_file"],"repeatable":false,"required":true,"summary":"Git commit-message file supplied by the commit-msg hook"}],"path":["commit-message"],"summary":"enforce [(i/N) ][TICKET] type(scope)!: description with safe mechanical fixes","usage":"code-standards commit-message [-h] COMMIT_MSG_FILE"},{"commands":[],"name":"doctor","options":[{"choices":[],"kind":"option","metavar":null,"names":["-h","--help"],"repeatable":false,"required":false,"summary":"Show this message and exit."},{"choices":["text","json"],"kind":"option","metavar":"OUTPUT_FORMAT","names":["--format"],"repeatable":false,"required":false,"summary":"output format (default: text)"},{"choices":[],"kind":"option","metavar":null,"names":["--repair"],"repeatable":false,"required":false,"summary":"transactionally repair safe drift with the executing bundle, then re-diagnose"},{"choices":[],"kind":"option","metavar":null,"names":["--no-install"],"repeatable":false,"required":false,"summary":"with --repair, update configuration without installing dependencies or hooks"}],"path":["doctor"],"summary":"diagnose adoption health and optionally repair safe drift","usage":"code-standards doctor [-h] [--format OUTPUT_FORMAT] [--repair] [--no-install]"},{"commands":[],"name":"setup","options":[{"choices":[],"kind":"option","metavar":null,"names":["-h","--help"],"repeatable":false,"required":false,"summary":"Show this message and exit."},{"choices":["pre-commit","lefthook","none"],"kind":"option","metavar":"HOOKS","names":["--hooks"],"repeatable":false,"required":false,"summary":"hook manager (default: detect Lefthook, otherwise pre-commit)"},{"choices":[],"kind":"option","metavar":"PYTHON_DEST","names":["--python-dest"],"repeatable":false,"required":false,"summary":"the directory that owns pyproject.toml (default: detected)"},{"choices":[],"kind":"option","metavar":"TYPESCRIPT_DEST","names":["--typescript-dest"],"repeatable":false,"required":false,"summary":"the directory that owns the npm lockfile (default: detected)"},{"choices":[],"kind":"option","metavar":"SWIFT_DEST","names":["--swift-dest"],"repeatable":false,"required":false,"summary":"the directory that owns one reviewed Swift project (default: mobile project detection)"},{"choices":[],"kind":"option","metavar":"KOTLIN_DEST","names":["--kotlin-dest"],"repeatable":false,"required":false,"summary":"the directory that owns one reviewed Android/KMP project (default: detected)"},{"choices":[],"kind":"option","metavar":null,"names":["--dry-run"],"repeatable":false,"required":false,"summary":"print the complete plan without writing"},{"choices":[],"kind":"option","metavar":null,"names":["--force"],"repeatable":false,"required":false,"summary":"replace conflicting generated lint configuration after review"},{"choices":[],"kind":"option","metavar":null,"names":["--no-install"],"repeatable":false,"required":false,"summary":"write wiring without installing dependencies or hooks"},{"choices":[],"kind":"option","metavar":null,"names":["--commit-policy-only"],"repeatable":false,"required":false,"summary":"adopt only commit-message and PR-history policy without changing language tooling"},{"choices":["checkov","detekt","eslint","ktlint","markdownlint","mobile-security","pyright","ruff","shellcheck","swiftformat","swiftlint","taplo","yamllint","zizmor"],"kind":"option","metavar":"ONLY","names":["--config"],"repeatable":true,"required":false,"summary":"select one config explicitly (repeatable)"}],"path":["setup"],"summary":"adopt or converge the repository in one idempotent operation","usage":"code-standards setup [-h] [--hooks HOOKS] [--python-dest PYTHON_DEST] [--typescript-dest TYPESCRIPT_DEST] [--swift-dest SWIFT_DEST] [--kotlin-dest KOTLIN_DEST] [--dry-run] [--force] [--no-install] [--commit-policy-only] [--config ONLY ...]"},{"commands":[],"name":"check","options":[{"choices":[],"kind":"option","metavar":null,"names":["-h","--help"],"repeatable":false,"required":false,"summary":"Show this message and exit."},{"choices":[],"kind":"option","metavar":null,"names":["--trust-repository-code"],"repeatable":false,"required":false,"summary":"allow executable repository ESLint configuration (generated hooks and CI set this explicitly)"},{"choices":[],"kind":"option","metavar":"JOBS","names":["--jobs"],"repeatable":false,"required":false,"summary":"overlap native and external analysis (default: 1)"},{"choices":[],"kind":"option","metavar":null,"names":["--skip-python-type-check"],"repeatable":false,"required":false,"summary":"leave BasedPyright to the repository's own required CI; configs stay managed"},{"choices":[],"kind":"option","metavar":null,"names":["--staged"],"repeatable":false,"required":false,"summary":"run custom rules on hook-supplied paths, or discover staged files when none are supplied"},{"choices":[],"kind":"option","metavar":"SELECTED_RULES","names":["--rule"],"repeatable":true,"required":false,"summary":"check only this custom ENGINE:ID rule (repeatable)"},{"choices":["text","json","sarif","github"],"kind":"option","metavar":"OUTPUT_FORMAT","names":["--format"],"repeatable":false,"required":false,"summary":""},{"choices":[],"kind":"option","metavar":"OUTPUT","names":["--output"],"repeatable":false,"required":false,"summary":"write JSON or SARIF atomically to PATH"},{"choices":[],"kind":"option","metavar":"MAX_ANNOTATIONS_PER_LEVEL","names":["--max-annotations-per-level"],"repeatable":false,"required":false,"summary":""},{"choices":[],"kind":"positional","metavar":"FILES","names":["files"],"repeatable":true,"required":false,"summary":"selected paths; when omitted, check the complete repository"}],"path":["check"],"summary":"run the complete quality gate or check selected paths or custom rules","usage":"code-standards check [-h] [--trust-repository-code] [--jobs JOBS] [--skip-python-type-check] [--staged] [--rule SELECTED_RULES ...] [--format OUTPUT_FORMAT] [--output OUTPUT] [--max-annotations-per-level MAX_ANNOTATIONS_PER_LEVEL] [FILES ...]"},{"commands":[],"name":"validate-slack-automations","options":[{"choices":[],"kind":"option","metavar":null,"names":["-h","--help"],"repeatable":false,"required":false,"summary":"Show this message and exit."},{"choices":[],"kind":"positional","metavar":"PATH","names":["slack_catalog"],"repeatable":false,"required":true,"summary":""}],"path":["validate-slack-automations"],"summary":"validate a versioned Slack automation catalog","usage":"code-standards validate-slack-automations [-h] PATH"},{"commands":[],"name":"observe","options":[{"choices":[],"kind":"option","metavar":null,"names":["-h","--help"],"repeatable":false,"required":false,"summary":"Show this message and exit."},{"choices":[],"kind":"option","metavar":"SELECTED_RULES","names":["--rule"],"repeatable":true,"required":true,"summary":"canonical ENGINE:ID selector (repeatable)"},{"choices":["text","json","sarif","github"],"kind":"option","metavar":"OUTPUT_FORMAT","names":["--format"],"repeatable":false,"required":false,"summary":""},{"choices":[],"kind":"option","metavar":"OUTPUT","names":["--output"],"repeatable":false,"required":false,"summary":""},{"choices":[],"kind":"option","metavar":null,"names":["--trust-repository-code"],"repeatable":false,"required":false,"summary":"allow repository ESLint configuration to execute"},{"choices":[],"kind":"option","metavar":"MAX_ANNOTATIONS_PER_LEVEL","names":["--max-annotations-per-level"],"repeatable":false,"required":false,"summary":""},{"choices":[],"kind":"positional","metavar":"FILES","names":["files"],"repeatable":true,"required":false,"summary":"selected paths; defaults to adopted verification paths"}],"path":["observe"],"summary":"report warning-stage findings with exit 0; invalid input or execution still exits 2","usage":"code-standards observe [-h] --rule SELECTED_RULES ... [--format OUTPUT_FORMAT] [--output OUTPUT] [--trust-repository-code] [--max-annotations-per-level MAX_ANNOTATIONS_PER_LEVEL] [FILES ...]"},{"commands":[],"name":"fix","options":[{"choices":[],"kind":"option","metavar":null,"names":["-h","--help"],"repeatable":false,"required":false,"summary":"Show this message and exit."},{"choices":[],"kind":"option","metavar":null,"names":["--staged"],"repeatable":false,"required":false,"summary":"fix only files staged in Git"},{"choices":[],"kind":"positional","metavar":"FILES","names":["files"],"repeatable":true,"required":false,"summary":"selected paths; when omitted, fix the complete repository"}],"path":["fix"],"summary":"apply safe formatting and lint fixes","usage":"code-standards fix [-h] [--staged] [FILES ...]"},{"commands":[],"name":"update","options":[{"choices":[],"kind":"option","metavar":null,"names":["-h","--help"],"repeatable":false,"required":false,"summary":"Show this message and exit."},{"choices":[],"kind":"option","metavar":null,"names":["--check"],"repeatable":false,"required":false,"summary":"preview without writing; exit 1 when changes exist"},{"choices":[],"kind":"option","metavar":null,"names":["--offline"],"repeatable":false,"required":false,"summary":"reconverge the executing bundle and skip every network-dependent install; does not resolve latest"},{"choices":[],"kind":"option","metavar":"VERSION","names":["--to"],"repeatable":false,"required":false,"summary":"resolve and apply exactly this immutable coherent bundle version"},{"choices":[],"kind":"option","metavar":null,"names":["--no-install"],"repeatable":false,"required":false,"summary":"do not install dependencies or hooks"}],"path":["update"],"summary":"upgrade to the latest published coherent Standards bundle","usage":"code-standards update [-h] [--check] [--offline] [--to VERSION] [--no-install]"},{"commands":[{"commands":[],"name":"init","options":[{"choices":[],"kind":"option","metavar":null,"names":["-h","--help"],"repeatable":false,"required":false,"summary":"Show this message and exit."},{"choices":[],"kind":"option","metavar":"OUTPUT","names":["--output"],"repeatable":false,"required":false,"summary":"baseline JSON (default: diagnostic-baseline.json)"},{"choices":[],"kind":"option","metavar":null,"names":["--trust-repository-code"],"repeatable":false,"required":false,"summary":"run repository-local analyzers that execute project code"},{"choices":[],"kind":"positional","metavar":"FILES","names":["files"],"repeatable":true,"required":false,"summary":"paths to analyze (default: the whole repository)"}],"path":["baseline","init"],"summary":"record the first diagnostic baseline","usage":"code-standards baseline init [-h] [--output OUTPUT] [--trust-repository-code] [FILES ...]"},{"commands":[],"name":"update","options":[{"choices":[],"kind":"option","metavar":null,"names":["-h","--help"],"repeatable":false,"required":false,"summary":"Show this message and exit."},{"choices":[],"kind":"option","metavar":"OUTPUT","names":["--output"],"repeatable":false,"required":false,"summary":"baseline JSON (default: diagnostic-baseline.json)"},{"choices":[],"kind":"option","metavar":null,"names":["--trust-repository-code"],"repeatable":false,"required":false,"summary":"run repository-local analyzers that execute project code"},{"choices":[],"kind":"option","metavar":"BASELINE_RULES","names":["--rule"],"repeatable":true,"required":false,"summary":"replace debt only for this newly promoted rule (repeatable; source:RULE is also accepted)"},{"choices":[],"kind":"positional","metavar":"FILES","names":["files"],"repeatable":true,"required":false,"summary":"paths to analyze (default: the whole repository)"}],"path":["baseline","update"],"summary":"re-record the diagnostic baseline after reviewed cleanup","usage":"code-standards baseline update [-h] [--output OUTPUT] [--trust-repository-code] [--rule BASELINE_RULES ...] [FILES ...]"}],"name":"baseline","options":[{"choices":[],"kind":"option","metavar":null,"names":["-h","--help"],"repeatable":false,"required":false,"summary":"Show this message and exit."}],"path":["baseline"],"summary":"grandfather today's findings so only new ones fail","usage":"code-standards baseline [-h] {init,update}"},{"commands":[{"commands":[],"name":"init","options":[{"choices":[],"kind":"option","metavar":null,"names":["-h","--help"],"repeatable":false,"required":false,"summary":"Show this message and exit."},{"choices":[],"kind":"option","metavar":"BASELINE","names":["--baseline"],"repeatable":false,"required":false,"summary":"budget JSON (default: suppression-baseline.json)"},{"choices":[],"kind":"option","metavar":"PACKAGE","names":["--package"],"repeatable":true,"required":false,"summary":"Python package root (repeatable)"},{"choices":[],"kind":"option","metavar":"EXCLUDE_SUBTREE","names":["--exclude-subtree"],"repeatable":true,"required":false,"summary":"generated or vendored subtree to persistently exclude (repeatable)"}],"path":["ratchet","init"],"summary":"create the first suppression budget","usage":"code-standards ratchet init [-h] [--baseline BASELINE] [--package PACKAGE ...] [--exclude-subtree EXCLUDE_SUBTREE ...]"},{"commands":[],"name":"check","options":[{"choices":[],"kind":"option","metavar":null,"names":["-h","--help"],"repeatable":false,"required":false,"summary":"Show this message and exit."},{"choices":[],"kind":"option","metavar":"BASELINE","names":["--baseline"],"repeatable":false,"required":false,"summary":"budget JSON (default: suppression-baseline.json)"},{"choices":[],"kind":"option","metavar":"PACKAGE","names":["--package"],"repeatable":true,"required":false,"summary":"Python package root (repeatable)"},{"choices":[],"kind":"option","metavar":"EXCLUDE_SUBTREE","names":["--exclude-subtree"],"repeatable":true,"required":false,"summary":"generated or vendored subtree to persistently exclude (repeatable)"}],"path":["ratchet","check"],"summary":"fail when suppression debt grows","usage":"code-standards ratchet check [-h] [--baseline BASELINE] [--package PACKAGE ...] [--exclude-subtree EXCLUDE_SUBTREE ...]"},{"commands":[],"name":"status","options":[{"choices":[],"kind":"option","metavar":null,"names":["-h","--help"],"repeatable":false,"required":false,"summary":"Show this message and exit."},{"choices":[],"kind":"option","metavar":"BASELINE","names":["--baseline"],"repeatable":false,"required":false,"summary":"budget JSON (default: suppression-baseline.json)"},{"choices":[],"kind":"option","metavar":"PACKAGE","names":["--package"],"repeatable":true,"required":false,"summary":"Python package root (repeatable)"},{"choices":[],"kind":"option","metavar":"EXCLUDE_SUBTREE","names":["--exclude-subtree"],"repeatable":true,"required":false,"summary":"generated or vendored subtree to persistently exclude (repeatable)"}],"path":["ratchet","status"],"summary":"show current suppression debt and available reductions","usage":"code-standards ratchet status [-h] [--baseline BASELINE] [--package PACKAGE ...] [--exclude-subtree EXCLUDE_SUBTREE ...]"},{"commands":[],"name":"update","options":[{"choices":[],"kind":"option","metavar":null,"names":["-h","--help"],"repeatable":false,"required":false,"summary":"Show this message and exit."},{"choices":[],"kind":"option","metavar":"BASELINE","names":["--baseline"],"repeatable":false,"required":false,"summary":"budget JSON (default: suppression-baseline.json)"},{"choices":[],"kind":"option","metavar":"PACKAGE","names":["--package"],"repeatable":true,"required":false,"summary":"Python package root (repeatable)"},{"choices":[],"kind":"option","metavar":"EXCLUDE_SUBTREE","names":["--exclude-subtree"],"repeatable":true,"required":false,"summary":"generated or vendored subtree to persistently exclude (repeatable)"},{"choices":[],"kind":"option","metavar":null,"names":["--allow-increase"],"repeatable":false,"required":false,"summary":"permit a reviewed increase in suppression debt"}],"path":["ratchet","update"],"summary":"lock in reviewed suppression-budget changes","usage":"code-standards ratchet update [-h] [--baseline BASELINE] [--package PACKAGE ...] [--exclude-subtree EXCLUDE_SUBTREE ...] [--allow-increase]"}],"name":"ratchet","options":[{"choices":[],"kind":"option","metavar":null,"names":["-h","--help"],"repeatable":false,"required":false,"summary":"Show this message and exit."}],"path":["ratchet"],"summary":"keep the Python suppression budget from growing","usage":"code-standards ratchet [-h] {init,check,status,update}"},{"commands":[{"commands":[],"name":"list","options":[{"choices":[],"kind":"option","metavar":null,"names":["-h","--help"],"repeatable":false,"required":false,"summary":"Show this message and exit."}],"path":["exclude","list"],"summary":"list the complete denylist","usage":"code-standards exclude list [-h]"},{"commands":[],"name":"add","options":[{"choices":[],"kind":"option","metavar":null,"names":["-h","--help"],"repeatable":false,"required":false,"summary":"Show this message and exit."},{"choices":["path","rule"],"kind":"positional","metavar":"{path,rule}","names":["exclude_kind"],"repeatable":false,"required":true,"summary":""},{"choices":[],"kind":"positional","metavar":"VALUE","names":["value"],"repeatable":false,"required":true,"summary":"repository-relative glob or canonical engine:rule selector"}],"path":["exclude","add"],"summary":"add one exact denylist entry","usage":"code-standards exclude add [-h] {path,rule} VALUE"},{"commands":[],"name":"remove","options":[{"choices":[],"kind":"option","metavar":null,"names":["-h","--help"],"repeatable":false,"required":false,"summary":"Show this message and exit."},{"choices":["path","rule"],"kind":"positional","metavar":"{path,rule}","names":["exclude_kind"],"repeatable":false,"required":true,"summary":""},{"choices":[],"kind":"positional","metavar":"VALUE","names":["value"],"repeatable":false,"required":true,"summary":"repository-relative glob or canonical engine:rule selector"}],"path":["exclude","remove"],"summary":"remove one exact denylist entry","usage":"code-standards exclude remove [-h] {path,rule} VALUE"}],"name":"exclude","options":[{"choices":[],"kind":"option","metavar":null,"names":["-h","--help"],"repeatable":false,"required":false,"summary":"Show this message and exit."}],"path":["exclude"],"summary":"inspect or change explicit path and rule exclusions","usage":"code-standards exclude [-h] {list,add,remove}"},{"commands":[{"commands":[],"name":"state","options":[{"choices":[],"kind":"option","metavar":null,"names":["-h","--help"],"repeatable":false,"required":false,"summary":"Show this message and exit."}],"path":["show","state"],"summary":"print detected adoption state as JSON","usage":"code-standards show state [-h]"},{"commands":[],"name":"configs","options":[{"choices":[],"kind":"option","metavar":null,"names":["-h","--help"],"repeatable":false,"required":false,"summary":"Show this message and exit."}],"path":["show","configs"],"summary":"list bundled configurations","usage":"code-standards show configs [-h]"},{"commands":[],"name":"config","options":[{"choices":[],"kind":"option","metavar":null,"names":["-h","--help"],"repeatable":false,"required":false,"summary":"Show this message and exit."},{"choices":["checkov","detekt","eslint","ktlint","markdownlint","mobile-security","pyright","ruff","shellcheck","swiftformat","swiftlint","taplo","yamllint","zizmor"],"kind":"positional","metavar":"NAME","names":["name"],"repeatable":false,"required":true,"summary":""}],"path":["show","config"],"summary":"print one bundled configuration path","usage":"code-standards show config [-h] NAME"},{"commands":[],"name":"peers","options":[{"choices":[],"kind":"option","metavar":null,"names":["-h","--help"],"repeatable":false,"required":false,"summary":"Show this message and exit."}],"path":["show","peers"],"summary":"show tested ESLint peer dependencies and install command","usage":"code-standards show peers [-h]"},{"commands":[],"name":"rules","options":[{"choices":[],"kind":"option","metavar":null,"names":["-h","--help"],"repeatable":false,"required":false,"summary":"Show this message and exit."}],"path":["show","rules"],"summary":"print the machine-readable custom-rule inventory","usage":"code-standards show rules [-h]"},{"commands":[],"name":"ci","options":[{"choices":[],"kind":"option","metavar":null,"names":["-h","--help"],"repeatable":false,"required":false,"summary":"Show this message and exit."},{"choices":[],"kind":"option","metavar":"OUTPUT","names":["--output"],"repeatable":false,"required":false,"summary":"write a managed workflow inside the repository"}],"path":["show","ci"],"summary":"print a complete versioned GitHub Actions standards workflow","usage":"code-standards show ci [-h] [--output OUTPUT]"}],"name":"show","options":[{"choices":[],"kind":"option","metavar":null,"names":["-h","--help"],"repeatable":false,"required":false,"summary":"Show this message and exit."}],"path":["show"],"summary":"print read-only package and adoption information","usage":"code-standards show [-h] {state,configs,config,peers,rules,ci}"},{"commands":[{"commands":[],"name":"setup","options":[{"choices":[],"kind":"option","metavar":null,"names":["-h","--help"],"repeatable":false,"required":false,"summary":"Show this message and exit."},{"choices":[],"kind":"option","metavar":null,"names":["--check"],"repeatable":false,"required":false,"summary":"print the deterministic setup plan without executing it"}],"path":["maintain","setup"],"summary":"install every standards development environment and repository hook","usage":"code-standards maintain setup [-h] [--check]"},{"commands":[],"name":"check","options":[{"choices":[],"kind":"option","metavar":null,"names":["-h","--help"],"repeatable":false,"required":false,"summary":"Show this message and exit."},{"choices":["ci-history","file-conventions","private-refs","versions"],"kind":"option","metavar":"REPO_ONLY","names":["--only"],"repeatable":true,"required":false,"summary":""},{"choices":[],"kind":"option","metavar":"COMMITS","names":["--commits"],"repeatable":false,"required":false,"summary":"also inspect commit messages in this revision range"},{"choices":[],"kind":"option","metavar":"POLICY_DEST","names":["--policy-root"],"repeatable":false,"required":false,"summary":"trusted repository policy root (default: --root)"},{"choices":[],"kind":"option","metavar":"PRIVATE_REFS_FILE","names":["--private-refs-file"],"repeatable":false,"required":false,"summary":"private-reference TOML outside the scanned repository"},{"choices":[],"kind":"option","metavar":null,"names":["--quiet"],"repeatable":false,"required":false,"summary":"hide finding details"}],"path":["maintain","check"],"summary":"run repository policy gates","usage":"code-standards maintain check [-h] [--only REPO_ONLY ...] [--commits COMMITS] [--policy-root POLICY_DEST] [--private-refs-file PRIVATE_REFS_FILE] [--quiet]"},{"commands":[],"name":"sync-ledger","options":[{"choices":[],"kind":"option","metavar":null,"names":["-h","--help"],"repeatable":false,"required":false,"summary":"Show this message and exit."},{"choices":[],"kind":"option","metavar":null,"names":["--check"],"repeatable":false,"required":false,"summary":"report drift without writing"}],"path":["maintain","sync-ledger"],"summary":"synchronize the rule compatibility ledger","usage":"code-standards maintain sync-ledger [-h] [--check]"},{"commands":[],"name":"comment-corpus","options":[{"choices":[],"kind":"option","metavar":null,"names":["-h","--help"],"repeatable":false,"required":false,"summary":"Show this message and exit."},{"choices":[],"kind":"positional","metavar":"ROOTS","names":["roots"],"repeatable":true,"required":true,"summary":""},{"choices":[],"kind":"option","metavar":"PRIVATE_JSONL","names":["--include-text"],"repeatable":false,"required":false,"summary":"write sensitive comment text to a new owner-readable file"}],"path":["maintain","comment-corpus"],"summary":"extract comments for calibration","usage":"code-standards maintain comment-corpus [-h] ROOTS ... [--include-text PRIVATE_JSONL]"},{"commands":[{"commands":[],"name":"check-tag","options":[{"choices":[],"kind":"option","metavar":null,"names":["-h","--help"],"repeatable":false,"required":false,"summary":"Show this message and exit."},{"choices":[],"kind":"positional","metavar":"TAG","names":["tag"],"repeatable":false,"required":true,"summary":""}],"path":["maintain","release","check-tag"],"summary":"require a release tag to match its package manifest","usage":"code-standards maintain release check-tag [-h] TAG"},{"commands":[],"name":"verify-tags","options":[{"choices":[],"kind":"option","metavar":null,"names":["-h","--help"],"repeatable":false,"required":false,"summary":"Show this message and exit."},{"choices":[],"kind":"option","metavar":"RELEASE_COMMIT","names":["--commit"],"repeatable":false,"required":false,"summary":"also require existing tags to match this publishing commit or an unchanged package tree"}],"path":["maintain","release","verify-tags"],"summary":"verify all manifest release tags on origin","usage":"code-standards maintain release verify-tags [-h] [--commit RELEASE_COMMIT]"},{"commands":[],"name":"create-tags","options":[{"choices":[],"kind":"option","metavar":null,"names":["-h","--help"],"repeatable":false,"required":false,"summary":"Show this message and exit."},{"choices":["contracts","typescript","bootstrap","python","sql","iac","standards","tsconfig"],"kind":"positional","metavar":"RELEASE_TARGETS","names":["release_targets"],"repeatable":true,"required":true,"summary":""},{"choices":[],"kind":"option","metavar":"RELEASE_COMMIT","names":["--commit"],"repeatable":false,"required":true,"summary":"exact commit that was published"},{"choices":[],"kind":"option","metavar":"ATTEMPTS","names":["--attempts"],"repeatable":false,"required":false,"summary":""},{"choices":[],"kind":"option","metavar":"DELAY_SECONDS","names":["--delay-seconds"],"repeatable":false,"required":false,"summary":""}],"path":["maintain","release","create-tags"],"summary":"create and push manifest release tags","usage":"code-standards maintain release create-tags [-h] RELEASE_TARGETS ... --commit RELEASE_COMMIT [--attempts ATTEMPTS] [--delay-seconds DELAY_SECONDS]"},{"commands":[],"name":"changes","options":[{"choices":[],"kind":"option","metavar":null,"names":["-h","--help"],"repeatable":false,"required":false,"summary":"Show this message and exit."},{"choices":[],"kind":"option","metavar":"BEFORE","names":["--before"],"repeatable":false,"required":true,"summary":""},{"choices":[],"kind":"option","metavar":"AFTER","names":["--after"],"repeatable":false,"required":true,"summary":""},{"choices":[],"kind":"option","metavar":"GITHUB_OUTPUT","names":["--github-output"],"repeatable":false,"required":true,"summary":""}],"path":["maintain","release","changes"],"summary":"emit package version changes between Git revisions","usage":"code-standards maintain release changes [-h] --before BEFORE --after AFTER --github-output GITHUB_OUTPUT"},{"commands":[],"name":"causality","options":[{"choices":[],"kind":"option","metavar":null,"names":["-h","--help"],"repeatable":false,"required":false,"summary":"Show this message and exit."},{"choices":[],"kind":"option","metavar":"BEFORE","names":["--before"],"repeatable":false,"required":true,"summary":""},{"choices":[],"kind":"option","metavar":"AFTER","names":["--after"],"repeatable":false,"required":true,"summary":""}],"path":["maintain","release","causality"],"summary":"require every publishable package change to bump its version","usage":"code-standards maintain release causality [-h] --before BEFORE --after AFTER"},{"commands":[],"name":"lock-age","options":[{"choices":[],"kind":"option","metavar":null,"names":["-h","--help"],"repeatable":false,"required":false,"summary":"Show this message and exit."},{"choices":[],"kind":"positional","metavar":"LOCKFILE","names":["lockfile"],"repeatable":false,"required":true,"summary":""},{"choices":[],"kind":"option","metavar":"MINIMUM_AGE","names":["--minimum-days"],"repeatable":false,"required":false,"summary":""},{"choices":[],"kind":"option","metavar":"RELEASE_EXCLUDE","names":["--exclude"],"repeatable":true,"required":false,"summary":""},{"choices":[],"kind":"option","metavar":"RELEASE_EXCLUDE_FILE","names":["--exclude-file"],"repeatable":true,"required":false,"summary":"line-oriented exact package@version exceptions (repeatable)"}],"path":["maintain","release","lock-age"],"summary":"enforce npm lockfile minimum release age","usage":"code-standards maintain release lock-age [-h] LOCKFILE [--minimum-days MINIMUM_AGE] [--exclude RELEASE_EXCLUDE ...] [--exclude-file RELEASE_EXCLUDE_FILE ...]"},{"commands":[],"name":"typescript","options":[{"choices":[],"kind":"option","metavar":null,"names":["-h","--help"],"repeatable":false,"required":false,"summary":"Show this message and exit."},{"choices":["check","pack","publish"],"kind":"positional","metavar":"RELEASE_MODE","names":["release_mode"],"repeatable":false,"required":true,"summary":""},{"choices":[],"kind":"option","metavar":"OUTPUT","names":["--output"],"repeatable":false,"required":false,"summary":"artifact directory (required for pack)"}],"path":["maintain","release","typescript"],"summary":"check, pack, or publish the TypeScript package","usage":"code-standards maintain release typescript [-h] RELEASE_MODE [--output OUTPUT]"},{"commands":[],"name":"verify-wheel","options":[{"choices":[],"kind":"option","metavar":null,"names":["-h","--help"],"repeatable":false,"required":false,"summary":"Show this message and exit."},{"choices":[],"kind":"positional","metavar":"WHEELS","names":["wheels"],"repeatable":true,"required":true,"summary":""}],"path":["maintain","release","verify-wheel"],"summary":"require non-empty license text in built Python wheels","usage":"code-standards maintain release verify-wheel [-h] WHEELS ..."},{"commands":[],"name":"verify-publications","options":[{"choices":[],"kind":"option","metavar":null,"names":["-h","--help"],"repeatable":false,"required":false,"summary":"Show this message and exit."},{"choices":[],"kind":"option","metavar":"ATTEMPTS","names":["--attempts"],"repeatable":false,"required":false,"summary":""},{"choices":[],"kind":"option","metavar":"DELAY_SECONDS","names":["--delay-seconds"],"repeatable":false,"required":false,"summary":""}],"path":["maintain","release","verify-publications"],"summary":"wait for every exact sibling publication required by Standards","usage":"code-standards maintain release verify-publications [-h] [--attempts ATTEMPTS] [--delay-seconds DELAY_SECONDS]"},{"commands":[],"name":"publish","options":[{"choices":[],"kind":"option","metavar":null,"names":["-h","--help"],"repeatable":false,"required":false,"summary":"Show this message and exit."},{"choices":["contracts","typescript","bootstrap","python","sql","iac","standards","tsconfig"],"kind":"positional","metavar":"RELEASE_TARGET","names":["release_target"],"repeatable":false,"required":true,"summary":""}],"path":["maintain","release","publish"],"summary":"build and publish one package through its native client","usage":"code-standards maintain release publish [-h] RELEASE_TARGET"}],"name":"release","options":[{"choices":[],"kind":"option","metavar":null,"names":["-h","--help"],"repeatable":false,"required":false,"summary":"Show this message and exit."}],"path":["maintain","release"],"summary":"validate and build publishable release artifacts","usage":"code-standards maintain release [-h] {check-tag,verify-tags,create-tags,changes,causality,lock-age,typescript,verify-wheel,verify-publications,publish}"},{"commands":[{"commands":[],"name":"check","options":[{"choices":[],"kind":"option","metavar":null,"names":["-h","--help"],"repeatable":false,"required":false,"summary":"Show this message and exit."}],"path":["maintain","docs","check"],"summary":"","usage":"code-standards maintain docs check [-h]"},{"commands":[],"name":"sync","options":[{"choices":[],"kind":"option","metavar":null,"names":["-h","--help"],"repeatable":false,"required":false,"summary":"Show this message and exit."}],"path":["maintain","docs","sync"],"summary":"","usage":"code-standards maintain docs sync [-h]"}],"name":"docs","options":[{"choices":[],"kind":"option","metavar":null,"names":["-h","--help"],"repeatable":false,"required":false,"summary":"Show this message and exit."}],"path":["maintain","docs"],"summary":"check or synchronize source-derived documentation","usage":"code-standards maintain docs [-h] {check,sync}"},{"commands":[{"commands":[],"name":"install","options":[{"choices":[],"kind":"option","metavar":null,"names":["-h","--help"],"repeatable":false,"required":false,"summary":"Show this message and exit."}],"path":["maintain","hooks","install"],"summary":"install Lefthook","usage":"code-standards maintain hooks install [-h]"}],"name":"hooks","options":[{"choices":[],"kind":"option","metavar":null,"names":["-h","--help"],"repeatable":false,"required":false,"summary":"Show this message and exit."}],"path":["maintain","hooks"],"summary":"manage the pinned repository hooks","usage":"code-standards maintain hooks [-h] {install}"},{"commands":[{"commands":[],"name":"manifest","options":[{"choices":[],"kind":"option","metavar":null,"names":["-h","--help"],"repeatable":false,"required":false,"summary":"Show this message and exit."}],"path":["maintain","rules","manifest"],"summary":"print the shipped rule inventory","usage":"code-standards maintain rules manifest [-h]"},{"commands":[],"name":"check","options":[{"choices":[],"kind":"option","metavar":null,"names":["-h","--help"],"repeatable":false,"required":false,"summary":"Show this message and exit."}],"path":["maintain","rules","check"],"summary":"verify the shipped rule inventory matches live registries","usage":"code-standards maintain rules check [-h]"},{"commands":[],"name":"sync","options":[{"choices":[],"kind":"option","metavar":null,"names":["-h","--help"],"repeatable":false,"required":false,"summary":"Show this message and exit."}],"path":["maintain","rules","sync"],"summary":"update the shipped rule inventory from live registries","usage":"code-standards maintain rules sync [-h]"},{"commands":[],"name":"new","options":[{"choices":[],"kind":"option","metavar":null,"names":["-h","--help"],"repeatable":false,"required":false,"summary":"Show this message and exit."},{"choices":[],"kind":"positional","metavar":"SELECTOR","names":["selector"],"repeatable":false,"required":true,"summary":"canonical ENGINE:ID selector"},{"choices":["architecture","correctness","maintainability","performance","security","style","testing"],"kind":"option","metavar":"RULE_CATEGORY","names":["--category"],"repeatable":false,"required":true,"summary":""},{"choices":[],"kind":"option","metavar":"RULE_SUMMARY","names":["--summary"],"repeatable":false,"required":true,"summary":""},{"choices":[],"kind":"option","metavar":null,"names":["--apply"],"repeatable":false,"required":false,"summary":"create the planned files"}],"path":["maintain","rules","new"],"summary":"plan or create author-owned rule and test skeletons","usage":"code-standards maintain rules new [-h] SELECTOR --category RULE_CATEGORY --summary RULE_SUMMARY [--apply]"},{"commands":[],"name":"stage-warning","options":[{"choices":[],"kind":"option","metavar":null,"names":["-h","--help"],"repeatable":false,"required":false,"summary":"Show this message and exit."},{"choices":[],"kind":"positional","metavar":"SELECTOR","names":["selector"],"repeatable":false,"required":true,"summary":"canonical ENGINE:ID selector"},{"choices":[],"kind":"option","metavar":null,"names":["--check"],"repeatable":false,"required":false,"summary":"report required staging without writing"}],"path":["maintain","rules","stage-warning"],"summary":"prepare one registered rule for warning-first publication","usage":"code-standards maintain rules stage-warning [-h] SELECTOR [--check]"},{"commands":[],"name":"promote-error","options":[{"choices":[],"kind":"option","metavar":null,"names":["-h","--help"],"repeatable":false,"required":false,"summary":"Show this message and exit."},{"choices":[],"kind":"positional","metavar":"SELECTOR","names":["selector"],"repeatable":false,"required":true,"summary":"canonical ENGINE:ID selector"},{"choices":[],"kind":"option","metavar":null,"names":["--check"],"repeatable":false,"required":false,"summary":"report required promotion without writing"}],"path":["maintain","rules","promote-error"],"summary":"promote one warning-staged rule to blocking error severity","usage":"code-standards maintain rules promote-error [-h] SELECTOR [--check]"},{"commands":[],"name":"prepare","options":[{"choices":[],"kind":"option","metavar":null,"names":["-h","--help"],"repeatable":false,"required":false,"summary":"Show this message and exit."},{"choices":[],"kind":"positional","metavar":"SELECTOR","names":["selector"],"repeatable":false,"required":true,"summary":"canonical ENGINE:ID selector"},{"choices":[],"kind":"option","metavar":null,"names":["--check"],"repeatable":false,"required":false,"summary":"report required preparation without writing"}],"path":["maintain","rules","prepare"],"summary":"validate and prepare one registered rule for warning-first publication","usage":"code-standards maintain rules prepare [-h] SELECTOR [--check]"},{"commands":[],"name":"verify","options":[{"choices":[],"kind":"option","metavar":null,"names":["-h","--help"],"repeatable":false,"required":false,"summary":"Show this message and exit."},{"choices":[],"kind":"positional","metavar":"SELECTOR","names":["selector"],"repeatable":false,"required":true,"summary":"canonical ENGINE:ID selector"}],"path":["maintain","rules","verify"],"summary":"validate one registered rule's authored files and public examples","usage":"code-standards maintain rules verify [-h] SELECTOR"},{"commands":[],"name":"bench","options":[{"choices":[],"kind":"option","metavar":null,"names":["-h","--help"],"repeatable":false,"required":false,"summary":"Show this message and exit."},{"choices":[],"kind":"positional","metavar":"FILES","names":["files"],"repeatable":true,"required":true,"summary":"Python files or directories"},{"choices":[],"kind":"option","metavar":"REPEATS","names":["--repeats"],"repeatable":false,"required":false,"summary":""},{"choices":[],"kind":"option","metavar":"SELECTED_RULES","names":["--rule"],"repeatable":true,"required":false,"summary":"python:ID selector; defaults to all Python rules"}],"path":["maintain","rules","bench"],"summary":"measure native Python analysis with diagnostic and source digests","usage":"code-standards maintain rules bench [-h] FILES ... [--repeats REPEATS] [--rule SELECTED_RULES ...]"},{"commands":[],"name":"changes","options":[{"choices":[],"kind":"option","metavar":null,"names":["-h","--help"],"repeatable":false,"required":false,"summary":"Show this message and exit."},{"choices":[],"kind":"option","metavar":"BEFORE","names":["--before"],"repeatable":false,"required":true,"summary":""},{"choices":[],"kind":"option","metavar":"AFTER","names":["--after"],"repeatable":false,"required":true,"summary":""},{"choices":["json","text"],"kind":"option","metavar":"OUTPUT_FORMAT","names":["--format"],"repeatable":false,"required":false,"summary":""},{"choices":["warning"],"kind":"option","metavar":"REQUIRED_ADDED_LEVEL","names":["--require-added-level"],"repeatable":false,"required":false,"summary":"fail when an added rule does not start at this level"}],"path":["maintain","rules","changes"],"summary":"compare rule inventory and policy between two Git revisions","usage":"code-standards maintain rules changes [-h] --before BEFORE --after AFTER [--format OUTPUT_FORMAT] [--require-added-level REQUIRED_ADDED_LEVEL]"},{"commands":[],"name":"evaluate","options":[{"choices":[],"kind":"option","metavar":null,"names":["-h","--help"],"repeatable":false,"required":false,"summary":"Show this message and exit."},{"choices":[],"kind":"option","metavar":"SELECTED_RULES","names":["--rule"],"repeatable":true,"required":true,"summary":"canonical ENGINE:ID selector (repeatable)"},{"choices":[],"kind":"option","metavar":"CORPUS_MANIFEST","names":["--corpus-manifest"],"repeatable":false,"required":false,"summary":"evaluate immutable repositories declared by a public corpus manifest"},{"choices":[],"kind":"option","metavar":"PRIVATE_OVERLAY","names":["--private-overlay"],"repeatable":false,"required":false,"summary":"merge an owner-readable private corpus overlay (requires --corpus-manifest)"},{"choices":["corpus","effective"],"kind":"option","metavar":"EVALUATION_SCOPE","names":["--scope"],"repeatable":false,"required":false,"summary":"corpus ignores baselines/rule exclusions; effective applies adopted repository policy"},{"choices":["json","text"],"kind":"option","metavar":"OUTPUT_FORMAT","names":["--format"],"repeatable":false,"required":false,"summary":""},{"choices":[],"kind":"option","metavar":"OUTPUT","names":["--output"],"repeatable":false,"required":false,"summary":""},{"choices":[],"kind":"option","metavar":null,"names":["--trust-repository-code"],"repeatable":false,"required":false,"summary":"allow executable repository ESLint configuration"},{"choices":[],"kind":"positional","metavar":"FILES","names":["files"],"repeatable":true,"required":false,"summary":""}],"path":["maintain","rules","evaluate"],"summary":"calibrate selected custom rules; findings exit 1 and invalid input or execution exits 2","usage":"code-standards maintain rules evaluate [-h] --rule SELECTED_RULES ... [--corpus-manifest CORPUS_MANIFEST] [--private-overlay PRIVATE_OVERLAY] [--scope EVALUATION_SCOPE] [--format OUTPUT_FORMAT] [--output OUTPUT] [--trust-repository-code] [FILES ...]"}],"name":"rules","options":[{"choices":[],"kind":"option","metavar":null,"names":["-h","--help"],"repeatable":false,"required":false,"summary":"Show this message and exit."}],"path":["maintain","rules"],"summary":"inspect live custom rules","usage":"code-standards maintain rules [-h] {manifest,check,sync,new,stage-warning,promote-error,prepare,verify,bench,changes,evaluate}"},{"commands":[{"commands":[],"name":"check","options":[{"choices":[],"kind":"option","metavar":null,"names":["-h","--help"],"repeatable":false,"required":false,"summary":"Show this message and exit."},{"choices":[],"kind":"option","metavar":null,"names":["--typescript-built"],"repeatable":false,"required":false,"summary":"reuse the TypeScript build completed by this verification run"}],"path":["maintain","catalog","check"],"summary":"verify the public catalog matches every live rule","usage":"code-standards maintain catalog check [-h] [--typescript-built]"},{"commands":[],"name":"sync","options":[{"choices":[],"kind":"option","metavar":null,"names":["-h","--help"],"repeatable":false,"required":false,"summary":"Show this message and exit."}],"path":["maintain","catalog","sync"],"summary":"update the public catalog from source-owned rule metadata","usage":"code-standards maintain catalog sync [-h]"}],"name":"catalog","options":[{"choices":[],"kind":"option","metavar":null,"names":["-h","--help"],"repeatable":false,"required":false,"summary":"Show this message and exit."}],"path":["maintain","catalog"],"summary":"maintain the source-derived public rule catalog","usage":"code-standards maintain catalog [-h] {check,sync}"},{"commands":[{"commands":[],"name":"check","options":[{"choices":[],"kind":"option","metavar":null,"names":["-h","--help"],"repeatable":false,"required":false,"summary":"Show this message and exit."}],"path":["maintain","cli-reference","check"],"summary":"verify the shipped reference matches the parser graph","usage":"code-standards maintain cli-reference check [-h]"},{"commands":[],"name":"sync","options":[{"choices":[],"kind":"option","metavar":null,"names":["-h","--help"],"repeatable":false,"required":false,"summary":"Show this message and exit."}],"path":["maintain","cli-reference","sync"],"summary":"update the shipped reference from the parser graph","usage":"code-standards maintain cli-reference sync [-h]"}],"name":"cli-reference","options":[{"choices":[],"kind":"option","metavar":null,"names":["-h","--help"],"repeatable":false,"required":false,"summary":"Show this message and exit."}],"path":["maintain","cli-reference"],"summary":"maintain the source-derived CLI reference","usage":"code-standards maintain cli-reference [-h] {check,sync}"}],"name":"maintain","options":[{"choices":[],"kind":"option","metavar":null,"names":["-h","--help"],"repeatable":false,"required":false,"summary":"Show this message and exit."}],"path":["maintain"],"summary":"repository policy, hooks, rule ledgers, and releases","usage":"code-standards maintain [-h] {setup,check,sync-ledger,comment-corpus,release,docs,hooks,rules,catalog,cli-reference}"}],"epilog":"Start with `code-standards setup`, then use `code-standards check`.","globalOptions":[{"choices":[],"kind":"option","metavar":null,"names":["-h","--help"],"repeatable":false,"required":false,"summary":"Show this message and exit."},{"choices":[],"kind":"option","metavar":"DEST","names":["--root"],"repeatable":false,"required":false,"summary":"repository root shared by the selected command (default: current directory)"},{"choices":[],"kind":"option","metavar":null,"names":["--version"],"repeatable":false,"required":false,"summary":""}],"launcher":{"install":"uv tool install --python 3.14 code-standards","runLatest":"uvx --no-config --isolated --python 3.14 --from code-standards code-standards"},"program":"code-standards","schemaVersion":1,"summary":"Adopt, check, fix, diagnose, and update sarj-ai standards (v8.13.1).","version":"8.13.1"}
|
|
@@ -22,6 +22,8 @@ CONFIG_NAMES: Final[Mapping[str, tuple[str, str]]] = MappingProxyType(
|
|
|
22
22
|
"taplo": ("taplo.strict.toml", ".taplo.toml"),
|
|
23
23
|
"yamllint": ("yamllint.strict.yaml", ".yamllint.yaml"),
|
|
24
24
|
"shellcheck": ("shellcheck.strict.rc", ".shellcheckrc"),
|
|
25
|
+
"zizmor": ("zizmor.strict.yml", "zizmor.yml"),
|
|
26
|
+
"checkov": ("checkov.strict.yml", ".checkov.yml"),
|
|
25
27
|
}
|
|
26
28
|
)
|
|
27
29
|
|
|
@@ -169,6 +169,8 @@ _CONFIG_TARGETS: Final = MappingProxyType(
|
|
|
169
169
|
"shellcheck": ("shellcheck.strict.rc", "shellcheck.strict.rc", ".shellcheckrc", "root"),
|
|
170
170
|
"taplo": ("taplo.strict.toml", "taplo.strict.toml", ".taplo.toml", "root"),
|
|
171
171
|
"yamllint": ("yamllint.strict.yaml", "yamllint.strict.yaml", ".yamllint.yaml", "root"),
|
|
172
|
+
"zizmor": ("zizmor.strict.yml", "zizmor.strict.yml", "zizmor.yml", "root"),
|
|
173
|
+
"checkov": ("checkov.strict.yml", "checkov.strict.yml", ".checkov.yml", "root"),
|
|
172
174
|
}
|
|
173
175
|
)
|
|
174
176
|
|
{code_standards-8.12.1 → code_standards-8.13.1}/src/sarj_standards/libs/adoption/lifecycle.py
RENAMED
|
@@ -17,7 +17,7 @@ from typing import TYPE_CHECKING, NamedTuple
|
|
|
17
17
|
|
|
18
18
|
from sarj_standards.libs.filesystem import is_link_like
|
|
19
19
|
from sarj_standards.libs.json_boundary import parse_json
|
|
20
|
-
from sarj_standards.libs.linting import runner
|
|
20
|
+
from sarj_standards.libs.linting import runner, security_tools
|
|
21
21
|
|
|
22
22
|
from . import manifest, packagemanager, scaffold, transaction
|
|
23
23
|
|
|
@@ -73,6 +73,12 @@ def install_commands(
|
|
|
73
73
|
hook_manager: manifest.HookManager = "pre-commit",
|
|
74
74
|
) -> list[Command]:
|
|
75
75
|
commands: list[Command] = []
|
|
76
|
+
for name in security_tools.TOOLS:
|
|
77
|
+
enabled = ecosystems.actions if name == "zizmor" else ecosystems.infrastructure
|
|
78
|
+
if enabled:
|
|
79
|
+
commands.append(
|
|
80
|
+
Command(f"prepare pinned {name}", (*security_tools.command(name, offline=False), "--version"), root)
|
|
81
|
+
)
|
|
76
82
|
if ecosystems.typescript_root is not None:
|
|
77
83
|
install_root = ecosystems.typescript_install_root or ecosystems.typescript_root
|
|
78
84
|
# Setup writes pnpm-workspace.yaml before this command executes because
|
{code_standards-8.12.1 → code_standards-8.13.1}/src/sarj_standards/libs/adoption/manifest.py
RENAMED
|
@@ -39,8 +39,10 @@ _TOML_COLUMN_WIDTH: Final = 80 # Taplo's default; the shipped strict config doe
|
|
|
39
39
|
|
|
40
40
|
|
|
41
41
|
class _UpstreamRuleEngine(StrEnum):
|
|
42
|
+
CHECKOV = "checkov"
|
|
42
43
|
ESLINT = "eslint"
|
|
43
44
|
SHELLCHECK = "shellcheck"
|
|
45
|
+
ZIZMOR = "zizmor"
|
|
44
46
|
|
|
45
47
|
|
|
46
48
|
#: Sibling distributions pinned exactly by `code-standards`.
|
|
@@ -91,6 +93,7 @@ SWIFT_CONFIGS: Final = ("swiftformat", "swiftlint")
|
|
|
91
93
|
KOTLIN_CONFIGS: Final = ("ktlint", "detekt")
|
|
92
94
|
MOBILE_CONFIGS: Final = ("mobile-security",)
|
|
93
95
|
SHARED_CONFIGS: Final = ("markdownlint", "shellcheck", "taplo", "yamllint")
|
|
96
|
+
SECURITY_CONFIGS: Final = ("zizmor", "checkov")
|
|
94
97
|
_SCHEMA_THREE_CONFIGS: Final = (*PYTHON_CONFIGS, *TYPESCRIPT_CONFIGS, *SHARED_CONFIGS)
|
|
95
98
|
ALL_CONFIGS: Final = (
|
|
96
99
|
*PYTHON_CONFIGS,
|
|
@@ -99,6 +102,7 @@ ALL_CONFIGS: Final = (
|
|
|
99
102
|
*KOTLIN_CONFIGS,
|
|
100
103
|
*MOBILE_CONFIGS,
|
|
101
104
|
*SHARED_CONFIGS,
|
|
105
|
+
*SECURITY_CONFIGS,
|
|
102
106
|
)
|
|
103
107
|
ALL_CAPABILITIES: Final = (*ALL_CONFIGS, *PYTHON_ANALYZERS)
|
|
104
108
|
DEFAULT_DURABLE_ARTIFACTS: Final = (
|
|
@@ -218,8 +222,14 @@ def default_configs(
|
|
|
218
222
|
has_swift: bool = False,
|
|
219
223
|
has_kotlin: bool = False,
|
|
220
224
|
has_mobile: bool = False,
|
|
225
|
+
has_actions: bool = False,
|
|
226
|
+
has_infrastructure: bool = False,
|
|
221
227
|
) -> tuple[str, ...]:
|
|
222
228
|
selected: set[str] = set(SHARED_CONFIGS)
|
|
229
|
+
if has_actions:
|
|
230
|
+
selected.add("zizmor")
|
|
231
|
+
if has_infrastructure:
|
|
232
|
+
selected.add("checkov")
|
|
223
233
|
if has_python:
|
|
224
234
|
selected.update(PYTHON_CONFIGS)
|
|
225
235
|
if has_typescript:
|
|
@@ -237,6 +247,7 @@ def default_configs(
|
|
|
237
247
|
*KOTLIN_CONFIGS,
|
|
238
248
|
*MOBILE_CONFIGS,
|
|
239
249
|
*SHARED_CONFIGS,
|
|
250
|
+
*SECURITY_CONFIGS,
|
|
240
251
|
)
|
|
241
252
|
return tuple(name for name in order if name in selected)
|
|
242
253
|
|
|
@@ -273,7 +284,6 @@ def _load_schema( # ruff: ignore[too-many-locals] - one validation boundary kee
|
|
|
273
284
|
raw_profile = data.get("profile", "standard")
|
|
274
285
|
capabilities_table = _manifest_table(data, "capabilities")
|
|
275
286
|
disabled = _string_list(capabilities_table, "disable", label="manifest [capabilities].disable")
|
|
276
|
-
supported_configs = ALL_CONFIGS if expected_schema == MANIFEST_SCHEMA else _SCHEMA_THREE_CONFIGS
|
|
277
287
|
supported_capabilities = ALL_CAPABILITIES if expected_schema == MANIFEST_SCHEMA else _SCHEMA_THREE_CONFIGS
|
|
278
288
|
unknown_capabilities = sorted(set(disabled) - set(supported_capabilities))
|
|
279
289
|
if unknown_capabilities:
|
|
@@ -282,17 +292,7 @@ def _load_schema( # ruff: ignore[too-many-locals] - one validation boundary kee
|
|
|
282
292
|
if declared is None:
|
|
283
293
|
msg = f"{path} must set a string `bundle` declaration"
|
|
284
294
|
raise TypeError(msg)
|
|
285
|
-
|
|
286
|
-
bundle_version = Version(declared)
|
|
287
|
-
except InvalidVersion as exc:
|
|
288
|
-
msg = f"{path} `bundle` must be a valid PEP 440 version"
|
|
289
|
-
raise ValueError(msg) from exc
|
|
290
|
-
enabled_configs = (
|
|
291
|
-
_SCHEMA_THREE_CONFIGS
|
|
292
|
-
if expected_schema == MANIFEST_SCHEMA and bundle_version < Version("7.8.0")
|
|
293
|
-
else supported_configs
|
|
294
|
-
)
|
|
295
|
-
names = [name for name in enabled_configs if name not in disabled]
|
|
295
|
+
names = tuple(name for name in _bundle_configs(declared, path, expected_schema) if name not in disabled)
|
|
296
296
|
if not isinstance(raw_profile, str) or raw_profile not in PROFILES:
|
|
297
297
|
msg = f"{path} `profile` must be one of: {', '.join(PROFILES)}"
|
|
298
298
|
raise ValueError(msg)
|
|
@@ -314,7 +314,7 @@ def _load_schema( # ruff: ignore[too-many-locals] - one validation boundary kee
|
|
|
314
314
|
hook_manager: HookManager = raw_hook_manager
|
|
315
315
|
return Manifest(
|
|
316
316
|
version=declared,
|
|
317
|
-
configs=
|
|
317
|
+
configs=names,
|
|
318
318
|
python_dest=_dest_value(dest_table, "python"),
|
|
319
319
|
typescript_dest=_dest_value(dest_table, "typescript"),
|
|
320
320
|
swift_dest=_dest_value(dest_table, "swift", root=root),
|
|
@@ -348,6 +348,19 @@ def _load_schema( # ruff: ignore[too-many-locals] - one validation boundary kee
|
|
|
348
348
|
)
|
|
349
349
|
|
|
350
350
|
|
|
351
|
+
def _bundle_configs(declared: str, path: Path, schema: int) -> tuple[str, ...]:
|
|
352
|
+
try:
|
|
353
|
+
version = Version(declared)
|
|
354
|
+
except InvalidVersion as exc:
|
|
355
|
+
msg = f"{path} `bundle` must be a valid PEP 440 version"
|
|
356
|
+
raise ValueError(msg) from exc
|
|
357
|
+
if schema != MANIFEST_SCHEMA or version < Version("7.8.0"):
|
|
358
|
+
return _SCHEMA_THREE_CONFIGS
|
|
359
|
+
if version < Version("8.13.0"):
|
|
360
|
+
return tuple(name for name in ALL_CONFIGS if name not in SECURITY_CONFIGS)
|
|
361
|
+
return ALL_CONFIGS
|
|
362
|
+
|
|
363
|
+
|
|
351
364
|
def _check_manifest_schema(data: Mapping[str, object], path: Path, expected_schema: int) -> None:
|
|
352
365
|
raw_schema = data.get("schema")
|
|
353
366
|
if type(raw_schema) is not int or raw_schema != expected_schema:
|
|
@@ -546,7 +559,7 @@ def validate_excluded_rule(selector: str) -> str:
|
|
|
546
559
|
engine, separator, rule = selector.partition(":")
|
|
547
560
|
if (
|
|
548
561
|
not separator
|
|
549
|
-
or engine not in {"ruff", "basedpyright",
|
|
562
|
+
or engine not in {"ruff", "basedpyright", *_UpstreamRuleEngine, *_SARJ_RULE_ENGINES}
|
|
550
563
|
or not rule
|
|
551
564
|
or rule != rule.strip()
|
|
552
565
|
):
|
|
@@ -592,10 +605,8 @@ def _validate_known_rule(engine: str, rule: str, selector: str) -> None:
|
|
|
592
605
|
upstream = _UpstreamRuleEngine(engine)
|
|
593
606
|
except ValueError:
|
|
594
607
|
return
|
|
595
|
-
if upstream is _UpstreamRuleEngine.
|
|
596
|
-
|
|
597
|
-
msg = f"unknown Standards rule exclusion: {selector}"
|
|
598
|
-
raise ValueError(msg)
|
|
608
|
+
if upstream is not _UpstreamRuleEngine.ESLINT:
|
|
609
|
+
_validate_source_tool_rule(upstream, rule, selector)
|
|
599
610
|
return
|
|
600
611
|
if rule.startswith("@sarj/"):
|
|
601
612
|
known = frozenset(f"@sarj/{name}" for name in shipped.rules.get(ledger.ESLINT, ()))
|
|
@@ -609,6 +620,21 @@ def _validate_known_rule(engine: str, rule: str, selector: str) -> None:
|
|
|
609
620
|
raise ValueError(msg)
|
|
610
621
|
|
|
611
622
|
|
|
623
|
+
def _validate_source_tool_rule(engine: _UpstreamRuleEngine, rule: str, selector: str) -> None:
|
|
624
|
+
from sarj_standards.libs.linting import ( # ruff: ignore[import-outside-top-level] -- defer analyzer imports while adoption initializes.
|
|
625
|
+
security_tools,
|
|
626
|
+
)
|
|
627
|
+
|
|
628
|
+
if engine is _UpstreamRuleEngine.SHELLCHECK:
|
|
629
|
+
valid = re.fullmatch(r"SC[0-9]{4}", rule) is not None
|
|
630
|
+
else:
|
|
631
|
+
known = security_tools.CHECKOV_CHECKS if engine is _UpstreamRuleEngine.CHECKOV else security_tools.ZIZMOR_RULES
|
|
632
|
+
valid = rule in known
|
|
633
|
+
if not valid:
|
|
634
|
+
msg = f"unknown Standards rule exclusion: {selector}"
|
|
635
|
+
raise ValueError(msg)
|
|
636
|
+
|
|
637
|
+
|
|
612
638
|
def _exclusion_overrides(
|
|
613
639
|
root: Path,
|
|
614
640
|
table: Mapping[str, object],
|