@7n/rules 1.5.1 → 1.6.0

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 (110) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/bin/n-rules.js +83 -21
  3. package/package.json +1 -1
  4. package/rules/abie/main.mdc +0 -6
  5. package/rules/js/check/docs/main.md +1 -1
  6. package/rules/js/check/main.mjs +6 -10
  7. package/rules/js/main.mdc +0 -1
  8. package/rules/js/vscode_extensions/template/extensions.json.snippet.json +4 -1
  9. package/rules/npm-module/main.mdc +0 -2
  10. package/rules/php/tooling/docs/main.md +1 -1
  11. package/rules/php/tooling/main.mjs +2 -7
  12. package/rules/python/tooling/docs/main.md +1 -1
  13. package/rules/python/tooling/main.mjs +2 -7
  14. package/rules/rego/lib/docs/run-external-tool.md +1 -2
  15. package/rules/rego/lib/run-external-tool.mjs +4 -1
  16. package/rules/security/main.mdc +0 -1
  17. package/rules/style/main.mdc +0 -1
  18. package/rules/style/tooling/docs/main.md +1 -1
  19. package/rules/style/tooling/main.mjs +2 -7
  20. package/rules/tauri/release/release.mdc +1 -1
  21. package/rules/text/formatting/docs/main.md +1 -1
  22. package/rules/text/formatting/main.mjs +11 -11
  23. package/rules/text/main.mdc +0 -1
  24. package/scripts/docs/skills-cli.md +3 -3
  25. package/scripts/lib/acp-runner.mjs +8 -10
  26. package/scripts/lib/docs/acp-runner.md +5 -5
  27. package/scripts/lib/docs/mirror-parity.md +1 -1
  28. package/scripts/lib/mirror-parity.mjs +49 -16
  29. package/scripts/skills-cli.mjs +1 -1
  30. package/rules/abie/clean_merged_ignore_branches/clean_merged_ignore_branches.mdc +0 -19
  31. package/rules/abie/clean_merged_ignore_branches/clean_merged_ignore_branches.rego +0 -81
  32. package/rules/abie/clean_merged_ignore_branches/concern.json +0 -11
  33. package/rules/abie/clean_merged_ignore_branches/docs/fix-clean_merged_ignore_branches.md +0 -31
  34. package/rules/abie/clean_merged_ignore_branches/docs/index.md +0 -9
  35. package/rules/abie/clean_merged_ignore_branches/fix-clean_merged_ignore_branches.mjs +0 -8
  36. package/rules/abie/clean_merged_ignore_branches/template/clean-merged-branch.yml.snippet.yml +0 -9
  37. package/rules/docker/lint_docker_yml/concern.json +0 -12
  38. package/rules/docker/lint_docker_yml/docs/fix-lint_docker_yml.md +0 -31
  39. package/rules/docker/lint_docker_yml/docs/index.md +0 -9
  40. package/rules/docker/lint_docker_yml/fix-lint_docker_yml.mjs +0 -5
  41. package/rules/docker/lint_docker_yml/lint_docker_yml.mdc +0 -14
  42. package/rules/docker/lint_docker_yml/lint_docker_yml.rego +0 -79
  43. package/rules/docker/lint_docker_yml/template/lint-docker.yml.snippet.yml +0 -41
  44. package/rules/js/lint_js_yml/concern.json +0 -12
  45. package/rules/js/lint_js_yml/docs/fix-lint_js_yml.md +0 -28
  46. package/rules/js/lint_js_yml/docs/index.md +0 -9
  47. package/rules/js/lint_js_yml/fix-lint_js_yml.mjs +0 -5
  48. package/rules/js/lint_js_yml/lint_js_yml.mdc +0 -14
  49. package/rules/js/lint_js_yml/lint_js_yml.rego +0 -117
  50. package/rules/js/lint_js_yml/template/lint-js.yml.snippet.yml +0 -40
  51. package/rules/k8s/lint_k8s_yml/concern.json +0 -12
  52. package/rules/k8s/lint_k8s_yml/docs/fix-lint_k8s_yml.md +0 -30
  53. package/rules/k8s/lint_k8s_yml/docs/index.md +0 -9
  54. package/rules/k8s/lint_k8s_yml/fix-lint_k8s_yml.mjs +0 -5
  55. package/rules/k8s/lint_k8s_yml/lint_k8s_yml.rego +0 -57
  56. package/rules/k8s/lint_k8s_yml/template/lint-k8s.yml.snippet.yml +0 -43
  57. package/rules/npm-module/npm_publish_yml/concern.json +0 -13
  58. package/rules/npm-module/npm_publish_yml/docs/fix-npm_publish_yml.md +0 -28
  59. package/rules/npm-module/npm_publish_yml/docs/index.md +0 -9
  60. package/rules/npm-module/npm_publish_yml/fix-npm_publish_yml.mjs +0 -8
  61. package/rules/npm-module/npm_publish_yml/template/npm-publish.yml.snippet.yml +0 -49
  62. package/rules/php/lint_php_yml/concern.json +0 -12
  63. package/rules/php/lint_php_yml/docs/fix-lint_php_yml.md +0 -28
  64. package/rules/php/lint_php_yml/docs/index.md +0 -9
  65. package/rules/php/lint_php_yml/fix-lint_php_yml.mjs +0 -5
  66. package/rules/php/lint_php_yml/lint_php_yml.mdc +0 -23
  67. package/rules/php/lint_php_yml/lint_php_yml.rego +0 -34
  68. package/rules/php/lint_php_yml/template/lint-php.yml.snippet.yml +0 -47
  69. package/rules/python/lint_python_yml/concern.json +0 -12
  70. package/rules/python/lint_python_yml/docs/fix-lint_python_yml.md +0 -27
  71. package/rules/python/lint_python_yml/docs/index.md +0 -9
  72. package/rules/python/lint_python_yml/fix-lint_python_yml.mjs +0 -5
  73. package/rules/python/lint_python_yml/lint_python_yml.mdc +0 -12
  74. package/rules/python/lint_python_yml/lint_python_yml.rego +0 -68
  75. package/rules/python/lint_python_yml/template/lint-python.yml.snippet.yml +0 -41
  76. package/rules/rust/lint_rust_yml/concern.json +0 -14
  77. package/rules/rust/lint_rust_yml/docs/fix-lint_rust_yml.md +0 -28
  78. package/rules/rust/lint_rust_yml/docs/index.md +0 -9
  79. package/rules/rust/lint_rust_yml/fix-lint_rust_yml.mjs +0 -5
  80. package/rules/rust/lint_rust_yml/lint_rust_yml.mdc +0 -17
  81. package/rules/rust/lint_rust_yml/lint_rust_yml.rego +0 -79
  82. package/rules/rust/lint_rust_yml/template/lint-rust.yml.snippet.yml +0 -44
  83. package/rules/rust/toolchain_cache/concern.json +0 -14
  84. package/rules/rust/toolchain_cache/docs/fix-toolchain_cache.md +0 -35
  85. package/rules/rust/toolchain_cache/docs/index.md +0 -12
  86. package/rules/rust/toolchain_cache/docs/main.md +0 -57
  87. package/rules/rust/toolchain_cache/fix-toolchain_cache.mjs +0 -117
  88. package/rules/rust/toolchain_cache/main.mjs +0 -177
  89. package/rules/rust/toolchain_cache/toolchain_cache.mdc +0 -23
  90. package/rules/security/lint_security_yml/concern.json +0 -14
  91. package/rules/security/lint_security_yml/docs/fix-lint_security_yml.md +0 -31
  92. package/rules/security/lint_security_yml/docs/index.md +0 -9
  93. package/rules/security/lint_security_yml/fix-lint_security_yml.mjs +0 -8
  94. package/rules/security/lint_security_yml/lint_security_yml.mdc +0 -7
  95. package/rules/security/lint_security_yml/lint_security_yml.rego +0 -33
  96. package/rules/security/lint_security_yml/template/lint-security.yml.snippet.yml +0 -31
  97. package/rules/style/lint_style_yml/concern.json +0 -12
  98. package/rules/style/lint_style_yml/docs/fix-lint_style_yml.md +0 -31
  99. package/rules/style/lint_style_yml/docs/index.md +0 -9
  100. package/rules/style/lint_style_yml/fix-lint_style_yml.mjs +0 -5
  101. package/rules/style/lint_style_yml/lint_style_yml.mdc +0 -13
  102. package/rules/style/lint_style_yml/lint_style_yml.rego +0 -38
  103. package/rules/style/lint_style_yml/template/lint-style.yml.snippet.yml +0 -39
  104. package/rules/text/lint_text/concern.json +0 -11
  105. package/rules/text/lint_text/docs/fix-lint_text.md +0 -28
  106. package/rules/text/lint_text/docs/index.md +0 -9
  107. package/rules/text/lint_text/fix-lint_text.mjs +0 -5
  108. package/rules/text/lint_text/lint_text.mdc +0 -19
  109. package/rules/text/lint_text/lint_text.rego +0 -104
  110. package/rules/text/lint_text/template/lint-text.yml.snippet.yml +0 -61
@@ -1,12 +0,0 @@
1
- ## Rego-gate: перевірка `.github/workflows/lint-python.yml`
2
-
3
- Rego-пакет: `python.lint_python_yml`
4
-
5
- Цільовий файл: `.github/workflows/lint-python.yml`
6
-
7
- Перевіряє (drift-safe через `--data template`):
8
-
9
- - кожен `uses` з канону (підмножина) присутній у workflow: `actions/checkout@v6`, `./.github/actions/setup-bun-deps`, `astral-sh/setup-uv@v8.0.0`;
10
- - кожен `run` з канону є substring серед run-кроків: `uv sync --frozen`, `n-rules lint python --no-fix`.
11
-
12
- Канонічний workflow: [lint-python.yml.snippet.yml](./template/lint-python.yml.snippet.yml)
@@ -1,68 +0,0 @@
1
- # Перевірка `.github/workflows/lint-python.yml` для правила python (python.mdc).
2
- #
3
- # Канон надходить через --data: { "template": { "snippet": ... } }
4
- # Структура --data сформована з template/lint-python.yml.snippet.yml.
5
- # Перевіряємо (drift-safe — усе ведеться з template, без inline-літералів):
6
- # - кожен `uses` з template (підмножина): actions/checkout@v6,
7
- # ./.github/actions/setup-bun-deps, astral-sh/setup-uv@v8.0.0;
8
- # - кожен `run` з template має бути присутнім (як substring) серед run-кроків
9
- # input'а: `uv sync --frozen`, `n-rules lint python --no-fix`.
10
- # Заборона Poetry-кроків (snok/install-poetry, `poetry install`) — через відсутність
11
- # у каноні: правило вимагає uv-кроки, а нав'язаних poetry-кроків у template немає.
12
- # Універсальні workflow-перевірки (name, concurrency, branches) — у `ga.workflow_common`.
13
- package python.lint_python_yml
14
-
15
- import rego.v1
16
-
17
- # Усі `uses` з канону workflow (по всіх job'ах template).
18
- expected_uses contains u if {
19
- some job in data.template.snippet.jobs
20
- some step in job.steps
21
- u := object.get(step, "uses", "")
22
- u != ""
23
- }
24
-
25
- # Усі `uses` з input workflow.
26
- actual_uses contains u if {
27
- some job in object.get(input, "jobs", {})
28
- some step in object.get(job, "steps", [])
29
- u := object.get(step, "uses", "")
30
- u != ""
31
- }
32
-
33
- # Конкатенація всіх `run`-кроків з input workflow.
34
- all_run_text := concat("\n", [run_text |
35
- some job in object.get(input, "jobs", {})
36
- some step in object.get(job, "steps", [])
37
- run_text := step_run_to_text(step)
38
- ])
39
-
40
- deny contains msg if {
41
- some required_use in expected_uses
42
- not required_use in actual_uses
43
- msg := sprintf("lint-python.yml: відсутній step з `uses: %s` (python.mdc)", [required_use])
44
- }
45
-
46
- deny contains msg if {
47
- msg := "lint-python.yml: actions/checkout@v6 потребує `with: persist-credentials: false` (python.mdc)"
48
- some job in object.get(input, "jobs", {})
49
- some step in object.get(job, "steps", [])
50
- step.uses == "actions/checkout@v6"
51
- creds := object.get(object.get(step, "with", {}), "persist-credentials", true)
52
- creds != false
53
- }
54
-
55
- deny contains msg if {
56
- some job in data.template.snippet.jobs
57
- some step in job.steps
58
- expected_run := object.get(step, "run", "")
59
- expected_run != ""
60
- not contains(all_run_text, expected_run)
61
- msg := sprintf("lint-python.yml: жоден крок run не містить %q (python.mdc)", [expected_run])
62
- }
63
-
64
- step_run_to_text(step) := step.run if is_string(step.run)
65
-
66
- else := concat("\n", [s | some s in step.run]) if is_array(step.run)
67
-
68
- else := ""
@@ -1,41 +0,0 @@
1
- name: Lint Python
2
-
3
- on:
4
- push:
5
- branches:
6
- - dev
7
- - main
8
- paths:
9
- - '**/*.py'
10
- - 'pyproject.toml'
11
- - 'uv.lock'
12
- - '.github/workflows/lint-python.yml'
13
-
14
- pull_request:
15
- branches:
16
- - dev
17
- - main
18
-
19
- concurrency:
20
- group: ${{ github.ref }}-${{ github.workflow }}
21
- cancel-in-progress: true
22
-
23
- jobs:
24
- python:
25
- runs-on: ubuntu-latest
26
- permissions:
27
- contents: read
28
- steps:
29
- - uses: actions/checkout@v6
30
- with:
31
- persist-credentials: false
32
-
33
- - uses: ./.github/actions/setup-bun-deps
34
-
35
- - uses: astral-sh/setup-uv@v8.0.0
36
-
37
- - name: Install dependencies (uv)
38
- run: uv sync --frozen
39
-
40
- - name: Lint Python
41
- run: bunx n-rules lint python --no-fix
@@ -1,14 +0,0 @@
1
- {
2
- "$schema": "https://unpkg.com/@7n/rules/schemas/concern.json",
3
- "fixability": "config",
4
- "policy": {
5
- "files": {
6
- "single": ".github/workflows/lint-rust.yml",
7
- "required": true
8
- },
9
- "missingMessage": ".github/workflows/lint-rust.yml не існує — створи з канонічним вмістом (rust.mdc)"
10
- },
11
- "requires": {
12
- "capability": "ci:github"
13
- }
14
- }
@@ -1,28 +0,0 @@
1
- ---
2
- type: JS Module
3
- title: fix-lint_rust_yml.mjs
4
- resource: npm/rules/rust/lint_rust_yml/fix-lint_rust_yml.mjs
5
- docgen:
6
- crc: f9900918
7
- model: openai-codex/gpt-5.4-mini
8
- tier: cloud-min
9
- score: 100
10
- issues: judge:inaccurate:0.99
11
- judgeModel: openai-codex/gpt-5.4-mini
12
- ---
13
-
14
- ## Огляд
15
-
16
- Функція `patterns` описує правила для вибірки шляхів і логів, пов’язаних із Rust lint-конфігурацією, зокрема для `lint-rust.yml` та `workflow path filter`. Вона свідомо не охоплює `.github` і `.git`, щоб не зачіпати службові та внутрішні шляхи. Поведінка read-only: лише читає дані й формує результат без запису у ФС чи БД.
17
-
18
- ## Поведінка
19
-
20
- 1. `patterns` формує набір правил для автоматичного виправлення lint-конфігурації Rust.
21
- 2. `patterns` цільово охоплює workflow-файл `.github/workflows/lint-rust.yml`, щоб підтримувати його в узгодженому стані.
22
- 3. `patterns` працює read-only щодо сховища: не змінює ФС чи БД, а лише описує, що саме треба виправити.
23
- 4. `patterns` свідомо не зачіпає `.github` і `.git` як окремі шляхи поза визначеним цільовим файлом.
24
-
25
- ## Гарантії поведінки
26
-
27
- - Read-only: не виконує операцій запису (ФС/БД).
28
- - Свідомо пропускає шляхи: `.github`, `.git`.
@@ -1,9 +0,0 @@
1
- ---
2
- type: Directory Index
3
- title: npm/rules/rust/lint_rust_yml
4
- resource: npm/rules/rust/lint_rust_yml/
5
- ---
6
-
7
- | Файл | Тип |
8
- | --------------------------------------------- | --------- |
9
- | [fix-lint_rust_yml.mjs](fix-lint_rust_yml.md) | JS Module |
@@ -1,5 +0,0 @@
1
- import { createTemplateFixPattern } from '../../../scripts/lib/fix/template-deep-merge.mjs'
2
-
3
- export const patterns = [
4
- createTemplateFixPattern({ id: 'rust-lint_rust_yml-template', targetPath: '.github/workflows/lint-rust.yml' })
5
- ]
@@ -1,17 +0,0 @@
1
- ## Перевірка `.github/workflows/lint-rust.yml`
2
-
3
- Rego-пакет: `rust.lint_rust_yml`
4
-
5
- Цільовий файл: `.github/workflows/lint-rust.yml`
6
-
7
- Перевіряє:
8
-
9
- - кожен `uses`-крок з канону присутній у workflow (підмножина): `actions/checkout@v6`, `dtolnay/rust-toolchain@stable`, `Swatinem/rust-cache@v2`
10
- - кожен `run`-крок з канону присутній як підрядок серед усіх `run`-кроків: `cargo fmt --all -- --check`, `cargo clippy --all-targets --all-features -- -D warnings`
11
- - канон завантажується через `--data` з template-сніпету — drift-safe: зміна шаблону автоматично рухає перевірку
12
-
13
- Канонічний template: [lint-rust.yml.snippet.yml](./template/lint-rust.yml.snippet.yml)
14
-
15
- Вимога `Swatinem/rust-cache@v2` після `dtolnay/rust-toolchain@…` тут перевіряється лише для цього конкретного файлу (як частина канону). Та сама вимога для **будь-якого** іншого workflow (coverage, release/build через `tauri-apps/tauri-action`, кастомні) — concern `rust/toolchain_cache`.
16
-
17
- Tauri-проєкти (`src-tauri/Cargo.toml`) додатково потребують у цьому файлі apt-кроку системних залежностей Linux перед Clippy — concern `tauri/linux_deps` (tauri.mdc), не частина канону тут.
@@ -1,79 +0,0 @@
1
- # Перевірка `.github/workflows/lint-rust.yml` для правила rust (rust.mdc).
2
- #
3
- # Канон надходить через --data: { "template": { "snippet": ... } }
4
- # Структура --data сформована з template/lint-rust.yml.snippet.yml.
5
- # Перевіряємо:
6
- # - кожен `uses` з template (підмножина): actions/checkout@v6,
7
- # dtolnay/rust-toolchain@stable, Swatinem/rust-cache@v2;
8
- # - кожен `run` з template має бути присутнім (як substring) серед
9
- # run-кроків input'а — drift-safe: зміна template одразу рухає перевірку.
10
- # Універсальні workflow-перевірки (name, concurrency, branches) — у `ga.workflow_common`.
11
- package rust.lint_rust_yml
12
-
13
- import rego.v1
14
-
15
- # Усі `uses` з канону workflow.
16
- expected_uses contains u if {
17
- some step in data.template.snippet.jobs.lint.steps
18
- u := object.get(step, "uses", "")
19
- u != ""
20
- }
21
-
22
- # Усі `uses` з input workflow.
23
- actual_uses contains u if {
24
- some job in object.get(input, "jobs", {})
25
- some step in object.get(job, "steps", [])
26
- u := object.get(step, "uses", "")
27
- u != ""
28
- }
29
-
30
- # Конкатенація всіх `run`-кроків з input workflow.
31
- all_run_text := concat("\n", [run_text |
32
- some job in object.get(input, "jobs", {})
33
- some step in object.get(job, "steps", [])
34
- run_text := step_run_to_text(step)
35
- ])
36
-
37
- # Крок dtolnay/rust-toolchain@stable має мати with.components з rustfmt і clippy.
38
- toolchain_step(step) if {
39
- uses := object.get(step, "uses", "")
40
- startswith(uses, "dtolnay/rust-toolchain@")
41
- }
42
-
43
- deny contains msg if {
44
- some required_use in expected_uses
45
- not required_use in actual_uses
46
- msg := sprintf("lint-rust.yml: відсутній step з `uses: %s` (rust.mdc)", [required_use])
47
- }
48
-
49
- deny contains msg if {
50
- some step in data.template.snippet.jobs.lint.steps
51
- expected_run := object.get(step, "run", "")
52
- expected_run != ""
53
- not contains(all_run_text, expected_run)
54
- msg := sprintf("lint-rust.yml: жоден крок run не містить %q (rust.mdc)", [expected_run])
55
- }
56
-
57
- deny contains msg if {
58
- msg := "lint-rust.yml: dtolnay/rust-toolchain step потребує with.components: rustfmt, clippy (rust.mdc)"
59
- some job in object.get(input, "jobs", {})
60
- some step in object.get(job, "steps", [])
61
- toolchain_step(step)
62
- components := object.get(object.get(step, "with", {}), "components", "")
63
- not contains(components, "rustfmt")
64
- }
65
-
66
- deny contains msg if {
67
- msg := "lint-rust.yml: dtolnay/rust-toolchain step потребує with.components: rustfmt, clippy (rust.mdc)"
68
- some job in object.get(input, "jobs", {})
69
- some step in object.get(job, "steps", [])
70
- toolchain_step(step)
71
- components := object.get(object.get(step, "with", {}), "components", "")
72
- not contains(components, "clippy")
73
- }
74
-
75
- step_run_to_text(step) := step.run if is_string(step.run)
76
-
77
- else := concat("\n", [s | some s in step.run]) if is_array(step.run)
78
-
79
- else := ""
@@ -1,44 +0,0 @@
1
- name: Lint Rust
2
-
3
- on:
4
- push:
5
- branches:
6
- - dev
7
- - main
8
- paths:
9
- - '**/*.rs'
10
- - '**/Cargo.toml'
11
- - '**/Cargo.lock'
12
- - '**/rustfmt.toml'
13
- - '**/clippy.toml'
14
-
15
- pull_request:
16
- branches:
17
- - dev
18
- - main
19
-
20
- concurrency:
21
- group: ${{ github.ref }}-${{ github.workflow }}
22
- cancel-in-progress: true
23
-
24
- jobs:
25
- lint:
26
- runs-on: ubuntu-latest
27
- permissions:
28
- contents: read
29
- steps:
30
- - uses: actions/checkout@v6
31
- with:
32
- persist-credentials: false
33
-
34
- - uses: dtolnay/rust-toolchain@stable
35
- with:
36
- components: rustfmt, clippy
37
-
38
- - uses: Swatinem/rust-cache@v2
39
-
40
- - name: Rustfmt
41
- run: cargo fmt --all -- --check
42
-
43
- - name: Clippy
44
- run: cargo clippy --all-targets --all-features -- -D warnings
@@ -1,14 +0,0 @@
1
- {
2
- "$schema": "https://unpkg.com/@7n/rules/schemas/concern.json",
3
- "fixability": "config",
4
- "lint": {
5
- "scope": "full",
6
- "glob": [
7
- ".github/workflows/*.yml",
8
- ".github/workflows/*.yaml"
9
- ]
10
- },
11
- "requires": {
12
- "capability": "ci:github"
13
- }
14
- }
@@ -1,35 +0,0 @@
1
- ---
2
- type: JS Module
3
- title: fix-toolchain_cache.mjs
4
- resource: npm/rules/rust/toolchain_cache/fix-toolchain_cache.mjs
5
- docgen:
6
- crc: ad42b3a8
7
- model: omlx/gemma-4-e4b-it-OptiQ-4bit
8
- score: 100
9
- issues: judge:inaccurate:0.97
10
- judgeModel: openai-codex/gpt-5.4-mini
11
- ---
12
-
13
- ## Огляд
14
-
15
- Управляє логікою кешування `Swatinem/rust-cache@v2` у системі. Додає необхідні кроки кешування до робочих процесів через `insertRustCache` та `addCacheWorkspaces`. Визначає шаблони для застосування трансформерів до файлів з конфігураційними порушеннями, використовуючи `patterns`. Забезпечує механізм fail-safe, перехоплюючи помилки без викиду винятків.
16
-
17
- ## Поведінка
18
-
19
- Поведінка:
20
- insertRustCache вставляє відсутній крок кешування `Swatinem/rust-cache@v2` після кроків, що використовують `dtolnay/rust-toolchain`, у робочих процесах, якщо це можливо.
21
- addCacheWorkspaces дописує конфігурацію `with: workspaces: <dir>` до існуючих кроків кешування `Swatinem/rust-cache@v2` у робочих процесах Tauri, якщо вони не містять цієї інформації.
22
- patterns надає визначення для автоматичного застосування трансформерів до файлів, що містять порушення конфігурації кешування, використовуючи логіку, визначену у файлі.
23
-
24
- ## Публічний API
25
-
26
- insertRustCache — вставляє інструмент для кешування Rust-засобів одразу після кроку з інструментарієм Rust, якщо в цьому ж завдання немає кроку кешування.
27
-
28
- addCacheWorkspaces — додає вказування робочих просторів до кожного кроку кешування Tauri-завдання, де ця інформація відсутня.
29
-
30
- patterns — визначає шаблони, за якими застосовується логіка.
31
-
32
- ## Гарантії поведінки
33
-
34
- - Перехоплює помилки і не пропускає винятків назовні (fail-safe).
35
- - Кешує результати в межах одного прогону.
@@ -1,12 +0,0 @@
1
- ---
2
- type: Directory Index
3
- title: npm/rules/rust/toolchain_cache
4
- resource: npm/rules/rust/toolchain_cache/
5
- ---
6
-
7
- # npm/rules/rust/toolchain_cache
8
-
9
- | Файл | Тип |
10
- | ------------------------------------------------- | --------- |
11
- | [fix-toolchain_cache.mjs](fix-toolchain_cache.md) | JS Module |
12
- | [main.mjs](main.md) | JS Module |
@@ -1,57 +0,0 @@
1
- ---
2
- type: JS Module
3
- title: main.mjs
4
- resource: npm/rules/rust/toolchain_cache/main.mjs
5
- docgen:
6
- crc: bcb01136
7
- model: omlx/gemma-4-e4b-it-OptiQ-4bit
8
- score: 100
9
- issues: judge:inaccurate:0.99
10
- judgeModel: openai-codex/gpt-5.4-mini
11
- ---
12
-
13
- ## Огляд
14
-
15
- Огляд
16
- Конструкція забезпечує перевірку у `.github/workflows/*.yml` того, що кожен job, що використовує `dtolnay/rust-toolchain@stable` для встановлення Rust toolchain, має подальший крок із кешуванням Rust за допомогою `Swatinem/rust-cache@v2`. Якщо job також виконує `tauri-apps/tauri-action` і `Cargo.toml` лежить у `src-tauri/`, кеш-крок повинен мати `with.workspaces` на цей каталог. Ця логіка контролюється згідно з принципами, описаними у (rust.mdc), використовуючи константи `MISSING_RUST_CACHE` та `MISSING_RUST_CACHE_WORKSPACES` для маркування відхилень.
17
-
18
- Поведінка
19
- MISSING_RUST_CACHE — константа-рядок, яка позначає відсутність необхідного кешування Rust toolchain.
20
- MISSING_RUST_CACHE_WORKSPACES — константа-рядок, що інформує про неправильну конфігурацію кешування для робочих просторів Rust.
21
- TOOLCHAIN_RE — визначення для ідентифікації кроків встановлення Rust toolchain.
22
- CACHE_RE — визначення для ідентифікації кроків, що використовують кешування Rust.
23
- scanToolchainSteps — аналізує вміст YAML-файлу workflow, виявляючи кроки встановлення toolchain та інформацію про кешування в межах одного job-а.
24
- tauriWorkspaceDir — визначає шлях до робочого простору Tauri, коли `Cargo.toml` не знаходиться в корені репозиторію.
25
- lint — сканує всі `.yml` та `.yaml` файли у каталозі `.github/workflows`, перевіряючи відповідність вимогам кешування.
26
- Інструмент працює лише з читанням конфігурацій (Read-only) та здійснює кешування інформації в межах поточного прогону.
27
-
28
- ## Поведінка
29
-
30
- **Поведінка**
31
- MISSING_RUST_CACHE — константа, що позначає відсутність необхідного кешування Rust toolchain.
32
- MISSING_RUST_CACHE_WORKSPACES — константа, що позначає неправильну конфігурацію кешування для робочих просторів Rust.
33
- TOOLCHAIN_RE — регулярний вираз для ідентифікації кроків, що встановлюють Rust toolchain.
34
- CACHE_RE — регулярний вираз для ідентифікації кроків, що використовують кешування Rust.
35
- scanToolchainSteps — аналізує вміст YAML-файлу workflow, виявляючи кроки встановлення toolchain та інформацію про кешування в межах одного job-а.
36
- tauriWorkspaceDir — визначає шлях до робочого простору Tauri, якщо файл `Cargo.toml` не розташований у корені проєкту.
37
- lint — сканує всі `.yml` та `.yaml` файли в каталозі `.github/workflows`, перевіряючи, чи присутні необхідні кешування для кроків Rust toolchain, і повідомляє про відхилення. При цьому ігнорує каталоги .github та .git.
38
-
39
- ## Публічний API
40
-
41
- Understood. As a technical writer adhering to the specified constraints, I will transform the provided list into concise, action-oriented behavioral documentation in Ukrainian, using only bulleted markers ("name — what it does"). I will avoid all introductory/concluding remarks, code blocks, signatures, types, parameters, stdlib mentions, regex descriptions, and internal private names.
42
-
43
- Here is the rewritten list:
44
-
45
- * MISSING_RUST_CACHE — Ідентифікатор, що позначає відсутність кешу Rust.
46
- * MISSING_RUST_CACHE_WORKSPACES — Ідентифікатор, що позначає відсутність кешу для Rust-робочих просторів.
47
- * TOOLCHAIN_RE — Маркер, що вказує на інструментарій.
48
- * CACHE_RE — Маркер, що стосується механізму кешування.
49
- * scanToolchainSteps — Виявляє всі етапи використання `dtolnay/rust-toolchain@…` у workflow-файлі, надаючи деталі про кешування та дії Tauri у відповідних завданнях.
50
- * tauriWorkspaceDir — Вказує на шлях до Rust-робочого простору для кешування, якщо `Cargo.toml` знаходиться в `src-tauri/`, інакше — не визначений.
51
- * lint — Здійснює перевірку коду на відповідність встановленим стандартам.
52
-
53
- ## Гарантії поведінки
54
-
55
- - Read-only: не виконує операцій запису (ФС/БД).
56
- - Кешує результати в межах одного прогону.
57
- - Свідомо пропускає шляхи: `.github`, `.git`.
@@ -1,117 +0,0 @@
1
- /** @see ./docs/fix-toolchain_cache.md */
2
-
3
- /**
4
- * T0-autofix для `rust/toolchain_cache` — детерміновано вставляє
5
- * `Swatinem/rust-cache@v2` одразу після кожного `dtolnay/rust-toolchain@…` кроку,
6
- * якому його бракує у своєму job-і, і дописує `with.workspaces` у Tauri-job-ах,
7
- * де Cargo.toml не в корені репо. Текстові splice-и (як `ga/workflows/fix-workflows.mjs`) —
8
- * зберігають коментарі/формат, мінімальний diff. Ідемпотентно: `scanToolchainSteps`
9
- * заново перевіряє стан файла на кожному прогоні.
10
- */
11
- import { applyToFiles } from '../../../scripts/utils/apply-to-files.mjs'
12
-
13
- import { MISSING_RUST_CACHE, MISSING_RUST_CACHE_WORKSPACES, scanToolchainSteps } from './main.mjs'
14
-
15
- /**
16
- * Індекс першого рядка після step-блоку, що починається на `stepLine`
17
- * (dash-колонка `dashCol`) — перший рядок з відступом не більшим за `dashCol`
18
- * (сусідній крок того самого рівня або dedent), або EOF.
19
- * @param {string[]} lines усі рядки
20
- * @param {number} stepLine індекс рядка кроку (`- uses: …`)
21
- * @param {number} dashCol колонка dash-а кроку
22
- * @returns {number} індекс вставки (кінець блоку кроку)
23
- */
24
- function stepBlockEnd(lines, stepLine, dashCol) {
25
- let j = stepLine + 1
26
- while (j < lines.length) {
27
- const line = lines[j]
28
- if (line.trim() !== '' && line.length - line.trimStart().length <= dashCol) break
29
- j++
30
- }
31
- return j
32
- }
33
-
34
- /**
35
- * Вставляє `Swatinem/rust-cache@v2` (з опційним `with.workspaces`) одразу після
36
- * кожного `dtolnay/rust-toolchain@…` кроку без cache-кроку в тому самому job-і.
37
- * @param {string} content вміст workflow-файла
38
- * @param {string} [workspaceDir] відносний шлях workspace-а для `with.workspaces` (опційно)
39
- * @returns {string|null} новий вміст або null, якщо нічого не змінилось
40
- */
41
- export function insertRustCache(content, workspaceDir) {
42
- const lines = content.split('\n')
43
- const missing = scanToolchainSteps(content).filter(s => !s.hasCache)
44
- if (missing.length === 0) return null
45
-
46
- /** @type {Array<{ at: number, text: string[] }>} */
47
- const inserts = []
48
- for (const step of missing) {
49
- const at = stepBlockEnd(lines, step.line, step.dashCol)
50
- const ind = ' '.repeat(step.dashCol)
51
- const text = [`${ind}- uses: Swatinem/rust-cache@v2`]
52
- if (workspaceDir && step.jobHasTauriAction) {
53
- text.push(`${ind} with:`, `${ind} workspaces: ${workspaceDir}`)
54
- }
55
- inserts.push({ at, text })
56
- }
57
- inserts.sort((a, b) => b.at - a.at) // згори вниз — індекси не зсуваються під час splice
58
- for (const ins of inserts) lines.splice(ins.at, 0, ...ins.text)
59
- return lines.join('\n')
60
- }
61
-
62
- /**
63
- * Дописує `with: workspaces: <dir>` у кожен уже наявний `Swatinem/rust-cache@…`
64
- * крок Tauri-job-а (`tauri-apps/tauri-action`), якому бракує `workspaces`.
65
- * @param {string} content вміст workflow-файла
66
- * @param {string} workspaceDir відносний шлях workspace-а
67
- * @returns {string|null} новий вміст або null, якщо нічого не змінилось
68
- */
69
- export function addCacheWorkspaces(content, workspaceDir) {
70
- const lines = content.split('\n')
71
- const targets = scanToolchainSteps(content).filter(s => s.hasCache && s.jobHasTauriAction && !s.cacheHasWorkspaces)
72
- if (targets.length === 0) return null
73
-
74
- /** @type {Array<{ at: number, text: string[] }>} */
75
- const inserts = []
76
- for (const step of targets) {
77
- const cacheLine = lines[step.cacheLine]
78
- const usesCol = cacheLine.indexOf('uses:')
79
- const ind = ' '.repeat(usesCol)
80
- const at = stepBlockEnd(lines, step.cacheLine, usesCol - 2)
81
- inserts.push({ at, text: [`${ind}with:`, `${ind} workspaces: ${workspaceDir}`] })
82
- }
83
- inserts.sort((a, b) => b.at - a.at)
84
- for (const ins of inserts) lines.splice(ins.at, 0, ...ins.text)
85
- return lines.join('\n')
86
- }
87
-
88
- /** @type {import('../../../scripts/lib/lint-surface/types.mjs').T0Pattern[]} */
89
- export const patterns = [
90
- {
91
- id: 'rust-toolchain-cache-insert',
92
- test: violations => violations.some(v => v.data?.kind === MISSING_RUST_CACHE && v.file),
93
- apply: (violations, ctx) => {
94
- const targets = violations.filter(v => v.data?.kind === MISSING_RUST_CACHE && v.file)
95
- const wsTargets = violations.filter(v => v.data?.kind === MISSING_RUST_CACHE_WORKSPACES)
96
- const workspaceDir = wsTargets.find(v => typeof v.data?.workspaceDir === 'string')?.data?.workspaceDir
97
- const touchedFiles = applyToFiles(targets, ctx, () => content => insertRustCache(content, workspaceDir))
98
- return touchedFiles.length > 0
99
- ? { touchedFiles, message: `Swatinem/rust-cache@v2 → ${touchedFiles.length} workflow(s)` }
100
- : { touchedFiles: [] }
101
- }
102
- },
103
- {
104
- id: 'rust-toolchain-cache-workspaces',
105
- test: violations => violations.some(v => v.data?.kind === MISSING_RUST_CACHE_WORKSPACES && v.file),
106
- apply: (violations, ctx) => {
107
- const targets = violations.filter(v => v.data?.kind === MISSING_RUST_CACHE_WORKSPACES && v.file)
108
- const touchedFiles = applyToFiles(targets, ctx, () => content => {
109
- const workspaceDir = targets.find(v => typeof v.data?.workspaceDir === 'string')?.data?.workspaceDir
110
- return workspaceDir ? addCacheWorkspaces(content, workspaceDir) : null
111
- })
112
- return touchedFiles.length > 0
113
- ? { touchedFiles, message: `with.workspaces → ${touchedFiles.length} workflow(s)` }
114
- : { touchedFiles: [] }
115
- }
116
- }
117
- ]