code-standards 8.12.0__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.
Files changed (136) hide show
  1. {code_standards-8.12.0 → code_standards-8.13.1}/PKG-INFO +8 -6
  2. code_standards-8.13.1/README.md +28 -0
  3. {code_standards-8.12.0 → code_standards-8.13.1}/pyproject.toml +11 -5
  4. {code_standards-8.12.0 → code_standards-8.13.1}/src/sarj_standards/api.py +25 -5
  5. {code_standards-8.12.0 → code_standards-8.13.1}/src/sarj_standards/cli/main.py +2 -0
  6. code_standards-8.13.1/src/sarj_standards/configs/checkov.strict.yml +15 -0
  7. code_standards-8.13.1/src/sarj_standards/configs/cli-reference.v1.json +1 -0
  8. {code_standards-8.12.0 → code_standards-8.13.1}/src/sarj_standards/configs/eslint.strict.mjs +5 -0
  9. code_standards-8.13.1/src/sarj_standards/configs/zizmor.strict.yml +2 -0
  10. {code_standards-8.12.0 → code_standards-8.13.1}/src/sarj_standards/libs/adoption/configs.py +2 -0
  11. {code_standards-8.12.0 → code_standards-8.13.1}/src/sarj_standards/libs/adoption/doctor.py +2 -0
  12. {code_standards-8.12.0 → code_standards-8.13.1}/src/sarj_standards/libs/adoption/lifecycle.py +7 -1
  13. {code_standards-8.12.0 → code_standards-8.13.1}/src/sarj_standards/libs/adoption/manifest.py +44 -18
  14. {code_standards-8.12.0 → code_standards-8.13.1}/src/sarj_standards/libs/adoption/scaffold.py +40 -2
  15. {code_standards-8.12.0 → code_standards-8.13.1}/src/sarj_standards/libs/adoption/service.py +1 -1
  16. {code_standards-8.12.0 → code_standards-8.13.1}/src/sarj_standards/libs/adoption/upgrade.py +15 -3
  17. {code_standards-8.12.0 → code_standards-8.13.1}/src/sarj_standards/libs/linting/external.py +128 -1
  18. {code_standards-8.12.0 → code_standards-8.13.1}/src/sarj_standards/libs/linting/runner.py +3 -2
  19. code_standards-8.13.1/src/sarj_standards/libs/linting/security_tools.py +477 -0
  20. {code_standards-8.12.0 → code_standards-8.13.1}/src/sarj_standards/libs/linting/textlint.py +132 -5
  21. {code_standards-8.12.0 → code_standards-8.13.1}/src/sarj_standards/libs/repository/docs.py +10 -2
  22. {code_standards-8.12.0 → code_standards-8.13.1}/src/sarj_standards/libs/repository/repository.py +2 -0
  23. {code_standards-8.12.0 → code_standards-8.13.1}/src/sarj_standards/libs/repository/third_party_catalog_artifact.py +95 -16
  24. code_standards-8.13.1/src/sarj_standards/schemas/rule-catalog.v1.json +1 -0
  25. code_standards-8.12.0/README.md +0 -26
  26. code_standards-8.12.0/src/sarj_standards/configs/cli-reference.v1.json +0 -1
  27. code_standards-8.12.0/src/sarj_standards/schemas/rule-catalog.v1.json +0 -1
  28. {code_standards-8.12.0 → code_standards-8.13.1}/.gitignore +0 -0
  29. {code_standards-8.12.0 → code_standards-8.13.1}/LICENSE +0 -0
  30. {code_standards-8.12.0 → code_standards-8.13.1}/src/sarj_standards/__init__.py +0 -0
  31. {code_standards-8.12.0 → code_standards-8.13.1}/src/sarj_standards/__main__.py +0 -0
  32. {code_standards-8.12.0 → code_standards-8.13.1}/src/sarj_standards/_meta.py +0 -0
  33. {code_standards-8.12.0 → code_standards-8.13.1}/src/sarj_standards/cli/__init__.py +0 -0
  34. {code_standards-8.12.0 → code_standards-8.13.1}/src/sarj_standards/configs/Mintfile.mobile.strict +0 -0
  35. {code_standards-8.12.0 → code_standards-8.13.1}/src/sarj_standards/configs/basedpyright.python315-watch.json +0 -0
  36. {code_standards-8.12.0 → code_standards-8.13.1}/src/sarj_standards/configs/basedpyright.strict.json +0 -0
  37. {code_standards-8.12.0 → code_standards-8.13.1}/src/sarj_standards/configs/detekt.strict.yml +0 -0
  38. {code_standards-8.12.0 → code_standards-8.13.1}/src/sarj_standards/configs/doctor.config.json +0 -0
  39. {code_standards-8.12.0 → code_standards-8.13.1}/src/sarj_standards/configs/eslint-compact-formatter.mjs +0 -0
  40. {code_standards-8.12.0 → code_standards-8.13.1}/src/sarj_standards/configs/eslint-selected-rules.mjs +0 -0
  41. {code_standards-8.12.0 → code_standards-8.13.1}/src/sarj_standards/configs/eslint.application.mjs +0 -0
  42. {code_standards-8.12.0 → code_standards-8.13.1}/src/sarj_standards/configs/eslint.peers.json +0 -0
  43. {code_standards-8.12.0 → code_standards-8.13.1}/src/sarj_standards/configs/ktlint.strict.editorconfig +0 -0
  44. {code_standards-8.12.0 → code_standards-8.13.1}/src/sarj_standards/configs/markdownlint.strict.yaml +0 -0
  45. {code_standards-8.12.0 → code_standards-8.13.1}/src/sarj_standards/configs/mobile-tools.versions.json +0 -0
  46. {code_standards-8.12.0 → code_standards-8.13.1}/src/sarj_standards/configs/mobsf.strict.yml +0 -0
  47. {code_standards-8.12.0 → code_standards-8.13.1}/src/sarj_standards/configs/pyright.strict.json +0 -0
  48. {code_standards-8.12.0 → code_standards-8.13.1}/src/sarj_standards/configs/ruff.application.toml +0 -0
  49. {code_standards-8.12.0 → code_standards-8.13.1}/src/sarj_standards/configs/ruff.python315-watch.toml +0 -0
  50. {code_standards-8.12.0 → code_standards-8.13.1}/src/sarj_standards/configs/ruff.strict.toml +0 -0
  51. {code_standards-8.12.0 → code_standards-8.13.1}/src/sarj_standards/configs/rule-calibration-campaign.v1.json +0 -0
  52. {code_standards-8.12.0 → code_standards-8.13.1}/src/sarj_standards/configs/rule-inventory.v1.json +0 -0
  53. {code_standards-8.12.0 → code_standards-8.13.1}/src/sarj_standards/configs/rule-ledger.json +0 -0
  54. {code_standards-8.12.0 → code_standards-8.13.1}/src/sarj_standards/configs/rule-level-source.mjs +0 -0
  55. {code_standards-8.12.0 → code_standards-8.13.1}/src/sarj_standards/configs/shellcheck.strict.rc +0 -0
  56. {code_standards-8.12.0 → code_standards-8.13.1}/src/sarj_standards/configs/swiftformat.strict +0 -0
  57. {code_standards-8.12.0 → code_standards-8.13.1}/src/sarj_standards/configs/swiftlint.strict.yml +0 -0
  58. {code_standards-8.12.0 → code_standards-8.13.1}/src/sarj_standards/configs/taplo.strict.toml +0 -0
  59. {code_standards-8.12.0 → code_standards-8.13.1}/src/sarj_standards/configs/yamllint.strict.yaml +0 -0
  60. {code_standards-8.12.0 → code_standards-8.13.1}/src/sarj_standards/libs/__init__.py +0 -0
  61. {code_standards-8.12.0 → code_standards-8.13.1}/src/sarj_standards/libs/adoption/__init__.py +0 -0
  62. {code_standards-8.12.0 → code_standards-8.13.1}/src/sarj_standards/libs/adoption/age_transition.py +0 -0
  63. {code_standards-8.12.0 → code_standards-8.13.1}/src/sarj_standards/libs/adoption/exclusions.py +0 -0
  64. {code_standards-8.12.0 → code_standards-8.13.1}/src/sarj_standards/libs/adoption/hooks.py +0 -0
  65. {code_standards-8.12.0 → code_standards-8.13.1}/src/sarj_standards/libs/adoption/launcher.py +0 -0
  66. {code_standards-8.12.0 → code_standards-8.13.1}/src/sarj_standards/libs/adoption/packagemanager.py +0 -0
  67. {code_standards-8.12.0 → code_standards-8.13.1}/src/sarj_standards/libs/adoption/retired_suppressions.py +0 -0
  68. {code_standards-8.12.0 → code_standards-8.13.1}/src/sarj_standards/libs/adoption/transaction.py +0 -0
  69. {code_standards-8.12.0 → code_standards-8.13.1}/src/sarj_standards/libs/adoption/uvtool.py +0 -0
  70. {code_standards-8.12.0 → code_standards-8.13.1}/src/sarj_standards/libs/catalogs/__init__.py +0 -0
  71. {code_standards-8.12.0 → code_standards-8.13.1}/src/sarj_standards/libs/catalogs/slack_automations.py +0 -0
  72. {code_standards-8.12.0 → code_standards-8.13.1}/src/sarj_standards/libs/corpus/__init__.py +0 -0
  73. {code_standards-8.12.0 → code_standards-8.13.1}/src/sarj_standards/libs/corpus/manifest.py +0 -0
  74. {code_standards-8.12.0 → code_standards-8.13.1}/src/sarj_standards/libs/corpus/snapshot.py +0 -0
  75. {code_standards-8.12.0 → code_standards-8.13.1}/src/sarj_standards/libs/diagnostics/__init__.py +0 -0
  76. {code_standards-8.12.0 → code_standards-8.13.1}/src/sarj_standards/libs/diagnostics/analysis.schema.json +0 -0
  77. {code_standards-8.12.0 → code_standards-8.13.1}/src/sarj_standards/libs/diagnostics/baseline.py +0 -0
  78. {code_standards-8.12.0 → code_standards-8.13.1}/src/sarj_standards/libs/diagnostics/models.py +0 -0
  79. {code_standards-8.12.0 → code_standards-8.13.1}/src/sarj_standards/libs/diagnostics/serialize.py +0 -0
  80. {code_standards-8.12.0 → code_standards-8.13.1}/src/sarj_standards/libs/diagnostics/source.py +0 -0
  81. {code_standards-8.12.0 → code_standards-8.13.1}/src/sarj_standards/libs/filesystem.py +0 -0
  82. {code_standards-8.12.0 → code_standards-8.13.1}/src/sarj_standards/libs/json_boundary.py +0 -0
  83. {code_standards-8.12.0 → code_standards-8.13.1}/src/sarj_standards/libs/linting/__init__.py +0 -0
  84. {code_standards-8.12.0 → code_standards-8.13.1}/src/sarj_standards/libs/linting/analysis.py +0 -0
  85. {code_standards-8.12.0 → code_standards-8.13.1}/src/sarj_standards/libs/linting/library_policy.py +0 -0
  86. {code_standards-8.12.0 → code_standards-8.13.1}/src/sarj_standards/libs/linting/mobile_tools.py +0 -0
  87. {code_standards-8.12.0 → code_standards-8.13.1}/src/sarj_standards/libs/linting/policy.py +0 -0
  88. {code_standards-8.12.0 → code_standards-8.13.1}/src/sarj_standards/libs/linting/repo_standards.py +0 -0
  89. {code_standards-8.12.0 → code_standards-8.13.1}/src/sarj_standards/libs/linting/scheduling.py +0 -0
  90. {code_standards-8.12.0 → code_standards-8.13.1}/src/sarj_standards/libs/linting/text_rule_base.py +0 -0
  91. {code_standards-8.12.0 → code_standards-8.13.1}/src/sarj_standards/libs/linting/text_rules/__init__.py +0 -0
  92. {code_standards-8.12.0 → code_standards-8.13.1}/src/sarj_standards/libs/linting/text_rules/_registry.py +0 -0
  93. {code_standards-8.12.0 → code_standards-8.13.1}/src/sarj_standards/libs/release/__init__.py +0 -0
  94. {code_standards-8.12.0 → code_standards-8.13.1}/src/sarj_standards/libs/release/_values.py +0 -0
  95. {code_standards-8.12.0 → code_standards-8.13.1}/src/sarj_standards/libs/release/artifacts.py +0 -0
  96. {code_standards-8.12.0 → code_standards-8.13.1}/src/sarj_standards/libs/release/causality.py +0 -0
  97. {code_standards-8.12.0 → code_standards-8.13.1}/src/sarj_standards/libs/release/changes.py +0 -0
  98. {code_standards-8.12.0 → code_standards-8.13.1}/src/sarj_standards/libs/release/process.py +0 -0
  99. {code_standards-8.12.0 → code_standards-8.13.1}/src/sarj_standards/libs/release/publish.py +0 -0
  100. {code_standards-8.12.0 → code_standards-8.13.1}/src/sarj_standards/libs/release/registry.py +0 -0
  101. {code_standards-8.12.0 → code_standards-8.13.1}/src/sarj_standards/libs/release/release_age.py +0 -0
  102. {code_standards-8.12.0 → code_standards-8.13.1}/src/sarj_standards/libs/release/retirement.py +0 -0
  103. {code_standards-8.12.0 → code_standards-8.13.1}/src/sarj_standards/libs/release/rollout.py +0 -0
  104. {code_standards-8.12.0 → code_standards-8.13.1}/src/sarj_standards/libs/release/tags.py +0 -0
  105. {code_standards-8.12.0 → code_standards-8.13.1}/src/sarj_standards/libs/release/typescript.py +0 -0
  106. {code_standards-8.12.0 → code_standards-8.13.1}/src/sarj_standards/libs/repository/__init__.py +0 -0
  107. {code_standards-8.12.0 → code_standards-8.13.1}/src/sarj_standards/libs/repository/cli_reference_artifact.py +0 -0
  108. {code_standards-8.12.0 → code_standards-8.13.1}/src/sarj_standards/libs/repository/comment_corpus.py +0 -0
  109. {code_standards-8.12.0 → code_standards-8.13.1}/src/sarj_standards/libs/repository/config_generation.py +0 -0
  110. {code_standards-8.12.0 → code_standards-8.13.1}/src/sarj_standards/libs/repository/hooks.py +0 -0
  111. {code_standards-8.12.0 → code_standards-8.13.1}/src/sarj_standards/libs/repository/ledger.py +0 -0
  112. {code_standards-8.12.0 → code_standards-8.13.1}/src/sarj_standards/libs/repository/ruff_freshness.py +0 -0
  113. {code_standards-8.12.0 → code_standards-8.13.1}/src/sarj_standards/libs/repository/rule_authoring.py +0 -0
  114. {code_standards-8.12.0 → code_standards-8.13.1}/src/sarj_standards/libs/repository/rule_catalog_artifact.py +0 -0
  115. {code_standards-8.12.0 → code_standards-8.13.1}/src/sarj_standards/libs/repository/rule_changes.py +0 -0
  116. {code_standards-8.12.0 → code_standards-8.13.1}/src/sarj_standards/libs/repository/rule_checkout.py +0 -0
  117. {code_standards-8.12.0 → code_standards-8.13.1}/src/sarj_standards/libs/repository/rule_examples.py +0 -0
  118. {code_standards-8.12.0 → code_standards-8.13.1}/src/sarj_standards/libs/repository/rule_inventory_artifact.py +0 -0
  119. {code_standards-8.12.0 → code_standards-8.13.1}/src/sarj_standards/libs/repository/rule_level_source.py +0 -0
  120. {code_standards-8.12.0 → code_standards-8.13.1}/src/sarj_standards/libs/repository/rule_lifecycle.py +0 -0
  121. {code_standards-8.12.0 → code_standards-8.13.1}/src/sarj_standards/libs/repository/rule_maintenance.py +0 -0
  122. {code_standards-8.12.0 → code_standards-8.13.1}/src/sarj_standards/libs/repository/rule_registration.py +0 -0
  123. {code_standards-8.12.0 → code_standards-8.13.1}/src/sarj_standards/libs/rules/__init__.py +0 -0
  124. {code_standards-8.12.0 → code_standards-8.13.1}/src/sarj_standards/libs/rules/catalog.py +0 -0
  125. {code_standards-8.12.0 → code_standards-8.13.1}/src/sarj_standards/libs/rules/contracts.py +0 -0
  126. {code_standards-8.12.0 → code_standards-8.13.1}/src/sarj_standards/libs/rules/corpus_runner.py +0 -0
  127. {code_standards-8.12.0 → code_standards-8.13.1}/src/sarj_standards/libs/rules/evaluation.py +0 -0
  128. {code_standards-8.12.0 → code_standards-8.13.1}/src/sarj_standards/libs/setup/__init__.py +0 -0
  129. {code_standards-8.12.0 → code_standards-8.13.1}/src/sarj_standards/libs/setup/repository.py +0 -0
  130. {code_standards-8.12.0 → code_standards-8.13.1}/src/sarj_standards/libs/typed_containers.py +0 -0
  131. {code_standards-8.12.0 → code_standards-8.13.1}/src/sarj_standards/libs/yaml_boundary.py +0 -0
  132. {code_standards-8.12.0 → code_standards-8.13.1}/src/sarj_standards/py.typed +0 -0
  133. {code_standards-8.12.0 → code_standards-8.13.1}/src/sarj_standards/schemas/__init__.py +0 -0
  134. {code_standards-8.12.0 → code_standards-8.13.1}/src/sarj_standards/schemas/_paths.py +0 -0
  135. {code_standards-8.12.0 → code_standards-8.13.1}/src/sarj_standards/schemas/rule-catalog.v1.schema.json +0 -0
  136. {code_standards-8.12.0 → 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.12.0
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.16.1
31
- Requires-Dist: sarj-python-lint==1.8.0
32
- Requires-Dist: sarj-rule-contracts==0.1.1
33
- Requires-Dist: sarj-sql-lint==0.18.3
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 check only selected Sarj custom rules. Exclusions, baselines, and severities still apply; upstream rules such as Ruff IDs are not supported. Native linters and ESLint execute only selected rules. ESLint retains configured parsers, options, severities, and suppression directives.
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.12.0"
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.1.1",
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.16.1",
33
- "sarj-python-lint==1.8.0",
34
- "sarj-sql-lint==0.18.3",
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
- run_eslint = rule_selection is None or RuleEngine.ESLINT in rule_selection.engines
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
- frozenset({"eslint"}) if rule_selection is not None else frozenset(adopted.enabled_capabilities)
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=frozenset({"eslint"}) if rule_selection is not None else None,
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 run_eslint
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.ESLINT if report.name == "eslint" else None
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"}
@@ -646,6 +646,10 @@ export function createConfig(options = {}) {
646
646
  },
647
647
  settings: { react: { version: "detect" } },
648
648
  rules: {
649
+ "no-restricted-properties": [
650
+ "error",
651
+ { property: "then", message: "Use async/await instead of .then()." },
652
+ ],
649
653
  "@typescript-eslint/no-explicit-any": "error",
650
654
  "@typescript-eslint/no-non-null-assertion": "error",
651
655
  "@typescript-eslint/no-deprecated": "error",
@@ -677,6 +681,7 @@ export function createConfig(options = {}) {
677
681
  "@typescript-eslint/no-misused-promises": "error",
678
682
  // The upstream rule flags every nested then/catch/finally call, including
679
683
  // deliberate fire-and-forget work and synchronous framework callbacks.
684
+ // Core no-restricted-properties bans only then; catch/finally stay available.
680
685
  // The typed @sarj rule below owns only semantics-preserving async returns.
681
686
  "promise/prefer-await-to-then": "off",
682
687
  "@typescript-eslint/require-await": "error",
@@ -0,0 +1,2 @@
1
+ # Local offline audits use upstream IDs; canonical Standards baselines own triage.
2
+ rules: {}
@@ -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
 
@@ -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
@@ -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
- try:
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=tuple(names),
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", "eslint", "shellcheck", "python", "sql", "iac", "text"}
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.SHELLCHECK:
596
- if re.fullmatch(r"SC[0-9]{4}", rule) is None:
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],