@nitra/cursor 3.22.0 → 3.23.1
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.
- package/.pi-template/extensions/n-cursor-adr/docs/index.md +181 -0
- package/AGENTS.template.md +4 -0
- package/CHANGELOG.md +37 -3
- package/bin/docs/n-cursor.md +636 -0
- package/bin/docs/rename-yaml-extensions.md +207 -0
- package/bin/n-cursor.js +30 -3
- package/package.json +1 -1
- package/rules/abie/docs/fix.md +18 -0
- package/rules/abie/js/docs/applies.md +26 -0
- package/rules/abie/js/docs/env_dns.md +32 -0
- package/rules/abie/js/docs/firebase_hosting.md +23 -0
- package/rules/abie/js/docs/hc_pairing.md +35 -0
- package/rules/abie/js/docs/ua_http_route.md +28 -0
- package/rules/abie/js/docs/ua_node_selector.md +28 -0
- package/rules/abie/lib/docs/enabled.md +29 -0
- package/rules/abie/lib/docs/env-dns.md +35 -0
- package/rules/abie/lib/docs/hc-yaml.md +33 -0
- package/rules/abie/lib/docs/http-route.md +44 -0
- package/rules/abie/lib/docs/k8s-tree.md +40 -0
- package/rules/abie/lib/docs/kustomization-patches.md +47 -0
- package/rules/abie/lib/docs/overlay-paths.md +38 -0
- package/rules/abie/lib/docs/yaml.md +29 -0
- package/rules/adr/docs/fix.md +148 -0
- package/rules/adr/js/docs/hooks.md +259 -0
- package/rules/bun/docs/fix.md +156 -0
- package/rules/bun/js/docs/layout.md +393 -0
- package/rules/capacitor/docs/fix.md +121 -0
- package/rules/capacitor/js/docs/platforms.md +295 -0
- package/rules/changelog/changelog.mdc +4 -2
- package/rules/changelog/docs/fix.md +174 -0
- package/rules/changelog/js/consistency.mjs +114 -13
- package/rules/changelog/js/docs/consistency.md +387 -0
- package/rules/changelog/lib/docs/package-manifest.md +210 -0
- package/rules/ci4/docs/fix.md +179 -0
- package/rules/ci4/js/docs/marksman_config.md +128 -0
- package/rules/docker/docker.mdc +8 -3
- package/rules/docker/docs/fix.md +171 -0
- package/rules/docker/js/docs/lint.md +258 -0
- package/rules/docker/lib/docs/docker-hadolint.md +184 -0
- package/rules/docker/lib/docs/docker-mirror.md +247 -0
- package/rules/docker/lib/docs/docker-native-addon.md +170 -0
- package/rules/docker/lib/docs/docker-nginx-user.md +219 -0
- package/rules/docker/lint/docs/lint.md +193 -0
- package/rules/efes/docs/fix.md +203 -0
- package/rules/feedback/docs/fix.md +140 -0
- package/rules/flow/docs/fix.md +152 -0
- package/rules/ga/docs/fix.md +158 -0
- package/rules/ga/js/docs/lint.md +100 -0
- package/rules/ga/js/docs/workflows.md +217 -0
- package/rules/ga/lint/docs/lint.md +209 -0
- package/rules/ga/policy/clean_merged_branch/clean_merged_branch.rego +11 -2
- package/rules/ga/policy/clean_merged_branch/template/clean-merged-branch.yml.snippet.yml +3 -4
- package/rules/graphql/docs/fix.md +126 -0
- package/rules/graphql/js/docs/tooling.md +264 -0
- package/rules/graphql/lib/docs/graphql-gql-scan.md +219 -0
- package/rules/hasura/docs/fix.md +120 -0
- package/rules/hasura/hasura.mdc +14 -0
- package/rules/hasura/js/docs/internal_urls.md +326 -0
- package/rules/image-avif/docs/fix.md +132 -0
- package/rules/image-avif/js/docs/avif_generation.md +241 -0
- package/rules/image-compress/docs/fix.md +150 -0
- package/rules/image-compress/js/docs/package_setup.md +191 -0
- package/rules/js-bun-db/docs/fix.md +148 -0
- package/rules/js-bun-db/js/docs/safety.md +231 -0
- package/rules/js-bun-db/js-bun-db.mdc +42 -13
- package/rules/js-bun-db/lib/docs/bun-sql-scan.md +347 -0
- package/rules/js-bun-redis/docs/fix.md +123 -0
- package/rules/js-bun-redis/js/docs/imports.md +176 -0
- package/rules/js-bun-redis/lib/docs/redis-imports.md +223 -0
- package/rules/js-lint/docs/fix.md +117 -0
- package/rules/js-lint/js/docs/lint.md +250 -0
- package/rules/js-lint/js/docs/tooling.md +348 -0
- package/rules/js-lint/js/docs/utils_imports.md +207 -0
- package/rules/js-lint-ci/docs/fix.md +154 -0
- package/rules/js-lint-ci/js/docs/lint.md +144 -0
- package/rules/js-mssql/docs/fix.md +128 -0
- package/rules/js-mssql/js/docs/deps.md +263 -0
- package/rules/js-mssql/lib/docs/mssql-pool-scan.md +367 -0
- package/rules/js-run/docs/fix.md +144 -0
- package/rules/js-run/js/docs/runtime.md +388 -0
- package/rules/js-run/lib/docs/bunyan-imports.md +117 -0
- package/rules/js-run/lib/docs/check-env-scan.md +433 -0
- package/rules/js-run/lib/docs/conn-file-rules.md +300 -0
- package/rules/js-run/lib/docs/conn-imports-scan.md +204 -0
- package/rules/js-run/lib/docs/promise-settimeout-scan.md +326 -0
- package/rules/k8s/docs/fix.md +129 -0
- package/rules/k8s/js/docs/manifests.md +344 -0
- package/rules/k8s/js/manifests.mjs +6 -2
- package/rules/k8s/k8s.mdc +4 -2
- package/rules/k8s/lint/docs/lint.md +411 -0
- package/rules/k8s/policy/network_policy/template/deployment.snippet.yaml +2 -0
- package/rules/k8s/policy/network_policy/template/stateful-set.snippet.yaml +2 -0
- package/rules/nginx-default-tpl/docs/fix.md +124 -0
- package/rules/nginx-default-tpl/js/docs/template.md +378 -0
- package/rules/npm-module/docs/fix.md +98 -0
- package/rules/npm-module/js/docs/package_structure.md +274 -0
- package/rules/npm-module/js/docs/rule_meta.md +137 -0
- package/rules/npm-module/js/docs/skill_meta.md +190 -0
- package/rules/php/docs/fix.md +107 -0
- package/rules/php/js/docs/tooling.md +152 -0
- package/rules/php/lint/docs/lint.md +215 -0
- package/rules/python/docs/fix.md +163 -0
- package/rules/python/js/docs/applies.md +108 -0
- package/rules/python/js/docs/tooling.md +153 -0
- package/rules/python/lint/docs/lint.md +322 -0
- package/rules/rego/docs/fix.md +121 -0
- package/rules/rego/js/docs/applies.md +174 -0
- package/rules/rego/js/docs/lint.md +118 -0
- package/rules/rego/lint/docs/lint.md +204 -0
- package/rules/release/docs/change.md +185 -0
- package/rules/release/docs/fix.md +119 -0
- package/rules/release/docs/release.md +222 -0
- package/rules/release/lib/docs/aggregate.md +246 -0
- package/rules/release/lib/docs/change-file.md +200 -0
- package/rules/release/lib/docs/fallback.md +203 -0
- package/rules/rust/docs/fix.md +129 -0
- package/rules/rust/js/docs/applies.md +140 -0
- package/rules/rust/lib/docs/has-cargo-toml.md +130 -0
- package/rules/security/docs/fix.md +86 -0
- package/rules/security/js/docs/lint.md +171 -0
- package/rules/security/js/docs/sample_secret.md +190 -0
- package/rules/security/js/docs/trufflehog.md +137 -0
- package/rules/security/js/lint.mjs +9 -1
- package/rules/style-lint/docs/fix.md +155 -0
- package/rules/style-lint/js/docs/lint.md +184 -0
- package/rules/style-lint/js/docs/tooling.md +194 -0
- package/rules/tauri/docs/fix.md +158 -0
- package/rules/tauri/js/docs/cargo_mutants_config.md +168 -0
- package/rules/tauri/js/docs/tooling.md +228 -0
- package/rules/test/coverage/coverage.mjs +15 -3
- package/rules/test/docs/fix.md +132 -0
- package/rules/test/js/data/stryker_config/docs/stryker-vue-macros-ignorer.md +138 -0
- package/rules/test/js/data/stryker_config/docs/stryker.config.baseline.md +134 -0
- package/rules/test/js/data/stryker_config/docs/stryker.config.vue.baseline.md +160 -0
- package/rules/test/js/data/vitest_config/docs/vitest.config.baseline.md +195 -0
- package/rules/test/js/docs/cargo_mutants_config.md +173 -0
- package/rules/test/js/docs/location.md +136 -0
- package/rules/test/js/docs/no-process-chdir.md +160 -0
- package/rules/test/js/docs/no-relative-fs-path.md +271 -0
- package/rules/test/js/docs/stryker_config.md +152 -0
- package/rules/test/js/docs/vitest-config-pool-forks.md +174 -0
- package/rules/text/docs/fix.md +118 -0
- package/rules/text/js/docs/forbidden-prettier.md +143 -0
- package/rules/text/js/docs/formatting.md +256 -0
- package/rules/text/js/docs/lint.md +122 -0
- package/rules/text/lint/docs/lint.md +220 -0
- package/rules/text/lint/docs/run-dotenv-linter.md +157 -0
- package/rules/text/lint/docs/run-shellcheck.md +212 -0
- package/rules/text/lint/docs/run-v8r.md +197 -0
- package/rules/vue/docs/fix.md +127 -0
- package/rules/vue/js/docs/packages.md +335 -0
- package/rules/vue/lib/docs/vue-forbidden-imports.md +261 -0
- package/rules/worktree/docs/fix.md +161 -0
- package/schemas/rule-meta.json +5 -1
- package/scripts/auto-rules.mjs +7 -4
- package/scripts/coverage-classify/docs/apply.md +202 -0
- package/scripts/coverage-classify/docs/cache.md +203 -0
- package/scripts/coverage-classify/docs/index.md +218 -0
- package/scripts/coverage-classify/docs/prompt.md +132 -0
- package/scripts/coverage-classify/docs/verdict-schema.md +169 -0
- package/scripts/coverage-fix-extract.mjs +122 -0
- package/scripts/coverage-fix.mjs +1 -1
- package/scripts/dispatcher/docs/graph.md +346 -0
- package/scripts/dispatcher/docs/index.md +236 -0
- package/scripts/dispatcher/docs/trace.md +296 -0
- package/scripts/dispatcher/index.mjs +1 -1
- package/scripts/dispatcher/lib/active.mjs +4 -8
- package/scripts/dispatcher/lib/commands.mjs +7 -11
- package/scripts/dispatcher/lib/docs/active.md +348 -0
- package/scripts/dispatcher/lib/docs/artifact.md +232 -0
- package/scripts/dispatcher/lib/docs/budget.md +167 -0
- package/scripts/dispatcher/lib/docs/capability.md +196 -0
- package/scripts/dispatcher/lib/docs/commands.md +210 -0
- package/scripts/dispatcher/lib/docs/events.md +182 -0
- package/scripts/dispatcher/lib/docs/executor.md +190 -0
- package/scripts/dispatcher/lib/docs/flow-lock.md +161 -0
- package/scripts/dispatcher/lib/docs/flow-resolve.md +267 -0
- package/scripts/dispatcher/lib/docs/gate.md +231 -0
- package/scripts/dispatcher/lib/docs/level.md +335 -0
- package/scripts/dispatcher/lib/docs/plan-panel.md +181 -0
- package/scripts/dispatcher/lib/docs/plan.md +200 -0
- package/scripts/dispatcher/lib/docs/planner.md +269 -0
- package/scripts/dispatcher/lib/docs/review.md +255 -0
- package/scripts/dispatcher/lib/docs/reviewer.md +240 -0
- package/scripts/dispatcher/lib/docs/snapshot.md +247 -0
- package/scripts/dispatcher/lib/docs/spec.md +203 -0
- package/scripts/dispatcher/lib/docs/state-store.md +303 -0
- package/scripts/dispatcher/lib/docs/subagent-runner.md +173 -0
- package/scripts/dispatcher/lib/executor.mjs +6 -1
- package/scripts/dispatcher/lib/flow-resolve.mjs +3 -1
- package/scripts/dispatcher/lib/level.mjs +29 -3
- package/scripts/dispatcher/lib/review.mjs +1 -1
- package/scripts/dispatcher/lib/subagent-runner.mjs +5 -3
- package/scripts/docs/auto-rules.md +376 -0
- package/scripts/docs/auto-skills.md +173 -0
- package/scripts/docs/build-agents-commands.md +183 -0
- package/scripts/docs/cli-entry.md +153 -0
- package/scripts/docs/coverage-fix.md +177 -0
- package/scripts/docs/ensure-nitra-cursor-dev-dependencies.md +189 -0
- package/scripts/lib/changed-files.mjs +4 -1
- package/scripts/lib/docs/changed-files.md +149 -0
- package/scripts/lib/docs/check-mdc-template-refs.md +222 -0
- package/scripts/lib/docs/check-reporter.md +175 -0
- package/scripts/lib/docs/discover-check-rules-from-cursor.md +157 -0
- package/scripts/lib/docs/discover-checkable-rules.md +165 -0
- package/scripts/lib/docs/ensure-tool.md +254 -0
- package/scripts/lib/docs/generated-markdown.md +275 -0
- package/scripts/lib/docs/gha-workflow.md +326 -0
- package/scripts/lib/docs/inline-template-links.md +303 -0
- package/scripts/lib/docs/list-rule-ids.md +156 -0
- package/scripts/lib/docs/load-cursor-config.md +147 -0
- package/scripts/lib/docs/mirror-parity.md +167 -0
- package/scripts/lib/worktree.mjs +26 -0
- package/scripts/worktree-cli.mjs +12 -2
- package/skills/coverage-fix/SKILL.md +34 -45
- package/skills/docgen/SKILL.md +44 -23
- package/skills/docgen/bench/etalon/firebase_hosting.md +19 -0
- package/skills/docgen/bench/etalon/k8s-tree.md +24 -0
- package/skills/docgen/bench/etalon/overlay-paths.md +24 -0
- package/skills/docgen/js/docgen-ignore.mjs +54 -0
- package/skills/docgen/js/docgen-scan.mjs +37 -21
- package/skills/llm-patch/SKILL.md +23 -2
- package/skills/start-check/SKILL.md +26 -53
- package/skills/start-check/js/check.mjs +211 -0
- package/skills/taze/SKILL.md +9 -3
- package/skills/taze/js/diff.mjs +154 -0
- package/types/bin/n-cursor.d.ts +1 -1
- package/skills/fix-tests/SKILL.md +0 -119
- package/skills/fix-tests/meta.json +0 -1
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
# `npm/rules/ga/lint/lint.mjs`
|
|
2
|
+
|
|
3
|
+
## Огляд
|
|
4
|
+
|
|
5
|
+
Модуль `lint.mjs` — це **CLI-обгортка над канонічним `lint-ga`** (правило `ga.mdc`), яка виконує комплексну перевірку GitHub Actions workflow-файлів проєкту. Модуль не є самостійним перевіряльником: він агрегує кілька стадій external-tools і делегує JS/Rego-частину перевірок в `rules/ga/fix.mjs::check()`.
|
|
6
|
+
|
|
7
|
+
Ключові зони відповідальності:
|
|
8
|
+
|
|
9
|
+
1. **Авто-встановлення обов'язкових бінарників** — `shellcheck` і `conftest` через `ensureTool` (підбирається менеджер пакетів per-platform: `brew`/`scoop`/GitHub Release).
|
|
10
|
+
2. **Preflight для `uv`** — м'яка перевірка, що `uv` (а отже `uvx`) є в `PATH`; інакше друкується hint з командами встановлення й функція повертає `1` без авто-install.
|
|
11
|
+
3. **Послідовний запуск трьох стадій перевірки** workflow-ів:
|
|
12
|
+
- `bunx github-actionlint` — синтаксис/семантика GH Actions, включно з вбудованим `shellcheck` у `run:` блоках (звідси preflight на `shellcheck`).
|
|
13
|
+
- `uvx zizmor --offline --collect=workflows .` — second-stage security-аудит workflow на ризики (через `uv`/`uvx`).
|
|
14
|
+
- `rules/ga/fix.mjs::check()` — Rego-полісі (батч `conftest` для `npm/policy/ga/`) **плюс** JS cross-file перевірки правил `ga.mdc`. Це та сама перевірка, що й `npx @nitra/cursor check ga`, тож `lint-ga` є суперсетом цієї підкоманди.
|
|
15
|
+
4. **Серіалізація запуску** через `runStandardLint(import.meta.dirname, steps)` згідно з каноном патерну `lint-*` (див. `.cursor/rules/scripts.mdc`, секція «Серіалізація важких CLI-команд») — без прямого `withLock`.
|
|
16
|
+
|
|
17
|
+
Plan B-патерн (rego-authoritative): сама Rego-полісі `npm/policy/ga/` запускає `rules/ga/fix.mjs::check()` як перший крок — `lint.mjs` про це не знає. Раніше `lint.mjs` сам спавнив `conftest` per-workflow для `ga.<name>` і `ga.workflow_common` (PoC); тепер уся логіка централізована в `rules/ga/fix.mjs`, тому одне джерело істини без дублювання між `lint-ga` і `npx @nitra/cursor check ga`.
|
|
18
|
+
|
|
19
|
+
Чому preflight на `shellcheck` обов'язковий: без нього `bunx github-actionlint` **мовчки** пропускає shell-перевірки у `run:` блоках; локально `bun lint-ga` лишається зеленим, а CI на `ubuntu-latest` (де `shellcheck` передвстановлений) падає. `ensureTool('shellcheck')` усуває цю різницю.
|
|
20
|
+
|
|
21
|
+
Чому `uv` — окремо й лише як hint: бінарник `uv` не входить у реєстр `ensureTool` для авто-install у цьому проєкті, тому модуль обмежується інформативною підказкою з командами встановлення (brew / curl / pip), щоб користувач не отримав неінформативну помилку від `uvx zizmor`.
|
|
22
|
+
|
|
23
|
+
Модуль експортує одну іменовану стрілкову функцію `runLintGaCli`, яку імпортує `bin/n-cursor.js` як обробник підкоманди `lint-ga`.
|
|
24
|
+
|
|
25
|
+
## Експорти / API
|
|
26
|
+
|
|
27
|
+
| Символ | Тип | Експорт | Опис |
|
|
28
|
+
| -------------- | ------------------------------- | ---------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
29
|
+
| `runLintGaCli` | `() => Promise<number>` (arrow) | `export const` (named) | Точка входу CLI-команди `lint-ga`. Обгортає `runLintGaSteps` у `runStandardLint(import.meta.dirname, ...)` — серіалізація + стандартні timing/exit-code/log конвенції. |
|
|
30
|
+
|
|
31
|
+
Жодних інших експортів модуль не надає: усі допоміжні функції (`resolvePreflightBin`, `printPreflightMissingMessage`, `preflight`, `runLintGaSteps`) і константа `UV_PREFLIGHT` — внутрішні.
|
|
32
|
+
|
|
33
|
+
JSDoc-typedef `PreflightDep` описує форму внутрішніх preflight-конфігів і не експортується.
|
|
34
|
+
|
|
35
|
+
## Функції
|
|
36
|
+
|
|
37
|
+
### `resolvePreflightBin(dep)`
|
|
38
|
+
|
|
39
|
+
```
|
|
40
|
+
function resolvePreflightBin(dep: PreflightDep): string | null
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
- **Параметри:**
|
|
44
|
+
- `dep: PreflightDep` — опис preflight-залежності з полями `bin`, `winBins`, `explanation`, `install`, `successMsg`.
|
|
45
|
+
- **Повертає:** `string | null` — абсолютний шлях до бінарника або `null`, якщо нічого не знайдено в `PATH`.
|
|
46
|
+
- **Поведінка:**
|
|
47
|
+
- Якщо `platform === 'win32'` (з `node:process`), спершу ітерує `dep.winBins` (наприклад, `['uv.exe']`) і повертає перший резолвлений шлях.
|
|
48
|
+
- Якщо жоден `winBins` не знайдено або платформа не Windows — фолбек на `resolveCmd(dep.bin)`.
|
|
49
|
+
- **Side effects:** немає (читання `PATH` через `resolveCmd` — pure-resolve).
|
|
50
|
+
|
|
51
|
+
### `printPreflightMissingMessage(dep)`
|
|
52
|
+
|
|
53
|
+
```
|
|
54
|
+
function printPreflightMissingMessage(dep: PreflightDep): void
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
- **Параметри:** `dep: PreflightDep`.
|
|
58
|
+
- **Повертає:** `void`.
|
|
59
|
+
- **Поведінка:** друкує у `stderr` блок із кількох рядків:
|
|
60
|
+
1. `❌ <bin> не знайдено в PATH.` (червоний хрестик у вигляді емодзі).
|
|
61
|
+
2. Пояснення з `dep.explanation` (одинарний відступ на 3 пробіли).
|
|
62
|
+
3. Заголовок `Встанови:` і список команд із `dep.install` з відступом на 5 пробілів.
|
|
63
|
+
4. Фінальний рядок-вказівка: `Деталі: ga.mdc → секція про lint-ga.`
|
|
64
|
+
- **Side effects:** запис у `process.stderr` через `console.error`. Жодних винятків не кидає.
|
|
65
|
+
|
|
66
|
+
### `preflight(dep)`
|
|
67
|
+
|
|
68
|
+
```
|
|
69
|
+
function preflight(dep: PreflightDep): boolean
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
- **Параметри:** `dep: PreflightDep`.
|
|
73
|
+
- **Повертає:** `boolean` — `true`, якщо бінарник знайдено в `PATH`; `false`, якщо ні.
|
|
74
|
+
- **Поведінка:**
|
|
75
|
+
- Викликає `resolvePreflightBin(dep)`.
|
|
76
|
+
- На pass: друкує `dep.successMsg` через `console.log` і повертає `true`.
|
|
77
|
+
- На fail: викликає `printPreflightMissingMessage(dep)` і повертає `false`.
|
|
78
|
+
- **Side effects:** запис у `stdout` (success) або `stderr` (fail) через `console.log`/`console.error`.
|
|
79
|
+
|
|
80
|
+
### `runLintGaSteps()`
|
|
81
|
+
|
|
82
|
+
```
|
|
83
|
+
async function runLintGaSteps(): Promise<number>
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
- **Параметри:** немає.
|
|
87
|
+
- **Повертає:** `Promise<number>` — `0`, якщо всі кроки успішні; інакше — exit-code першого кроку, що впав.
|
|
88
|
+
- **Поведінка (послідовно):**
|
|
89
|
+
1. `ensureTool('shellcheck')` — авто-install або hard-fail (кидає виняток, який підхоплює `runStandardLint` і конвертує в `exit 1`).
|
|
90
|
+
2. `ensureTool('conftest')` — те саме.
|
|
91
|
+
3. `preflight(UV_PREFLIGHT)` — якщо `uv` не знайдено, повертає `1` без падіння (hint-only).
|
|
92
|
+
4. `runLintStep('actionlint', 'bunx', ['github-actionlint'])` → якщо код ≠ 0, повертає його.
|
|
93
|
+
5. `runLintStep('zizmor', 'uvx', ['zizmor', '--offline', '--collect=workflows', '.'])` → якщо код ≠ 0, повертає його.
|
|
94
|
+
6. Друкує заголовок `▶ check-ga (rego-полісі npm/policy/ga/ + JS cross-file перевірки)` і повертає `await checkGa()` (з `../js/workflows.mjs`).
|
|
95
|
+
- **Side effects:**
|
|
96
|
+
- Можлива інсталяція пакетів через `ensureTool` (мутує систему: brew/scoop/завантаження бінарників).
|
|
97
|
+
- Спавн процесів `bunx`, `uvx` через `runLintStep`.
|
|
98
|
+
- Виклик `conftest` (батчем) і JS-перевірки всередині `checkGa()`.
|
|
99
|
+
- Запис у `stdout`/`stderr`.
|
|
100
|
+
|
|
101
|
+
### `runLintGaCli` (експортовано)
|
|
102
|
+
|
|
103
|
+
```
|
|
104
|
+
export const runLintGaCli: () => Promise<number>
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
- **Параметри:** немає.
|
|
108
|
+
- **Повертає:** `Promise<number>` — результат `runStandardLint(...)`, тобто фінальний exit-code лінт-команди.
|
|
109
|
+
- **Поведінка:** обгортає `runLintGaSteps` у `runStandardLint(import.meta.dirname, runLintGaSteps)`. `import.meta.dirname` визначає каталог `npm/rules/ga/lint/`, що використовується для лок-файлу серіалізації та для службових логів.
|
|
110
|
+
- **Side effects:** успадковуються від `runStandardLint` (lock-файл / cleanup) і `runLintGaSteps`.
|
|
111
|
+
|
|
112
|
+
## Внутрішні дані
|
|
113
|
+
|
|
114
|
+
### `UV_PREFLIGHT`
|
|
115
|
+
|
|
116
|
+
```
|
|
117
|
+
const UV_PREFLIGHT: PreflightDep
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
Конфігурація preflight для `uv`:
|
|
121
|
+
|
|
122
|
+
- `bin: 'uv'`
|
|
123
|
+
- `winBins: ['uv.exe']`
|
|
124
|
+
- `explanation`: двохрядкове пояснення про те, що без `uv`/`uvx` не запуститься `uvx zizmor` (second-stage аудит workflow на ризики GitHub Actions).
|
|
125
|
+
- `install`:
|
|
126
|
+
- `'macOS: brew install uv'`
|
|
127
|
+
- `'Universal: curl -LsSf https://astral.sh/uv/install.sh | sh'`
|
|
128
|
+
- `'pip: pip install uv'`
|
|
129
|
+
- `successMsg: '✅ uv знайдено в PATH — uvx zizmor запуститься'`
|
|
130
|
+
|
|
131
|
+
### `PreflightDep` (JSDoc typedef)
|
|
132
|
+
|
|
133
|
+
Структура опису однієї preflight-залежності:
|
|
134
|
+
|
|
135
|
+
| Поле | Тип | Опис |
|
|
136
|
+
| ------------- | ---------- | ---------------------------------------------------------------------------------------------- |
|
|
137
|
+
| `bin` | `string` | Базове ім'я виконуваного файлу (на Windows додається `.exe` за потреби — через `winBins`). |
|
|
138
|
+
| `winBins` | `string[]` | Альтернативні імена на Windows (наприклад, `shellcheck.exe`); якщо порожньо — фолбек на `bin`. |
|
|
139
|
+
| `explanation` | `string` | 1–2 рядки, що пояснюють наслідки відсутності бінарника. |
|
|
140
|
+
| `install` | `string[]` | Список рядків з командами встановлення (друкуються «як є», з відступом). |
|
|
141
|
+
| `successMsg` | `string` | Повідомлення, яке друкується на pass-шлях preflight-у. |
|
|
142
|
+
|
|
143
|
+
## Залежності
|
|
144
|
+
|
|
145
|
+
### Зовнішні (Node.js core)
|
|
146
|
+
|
|
147
|
+
- `node:process` — імпортується `platform` (рядок типу `'darwin' | 'linux' | 'win32' | ...`) для гілки Windows у `resolvePreflightBin`.
|
|
148
|
+
|
|
149
|
+
### Внутрішні (проєктні)
|
|
150
|
+
|
|
151
|
+
- `../js/workflows.mjs` — імпорт `check as checkGa`. Виконує Rego-полісі (батч `conftest` для `npm/policy/ga/`) і JS cross-file перевірки правил `ga.mdc`. Це фінальний крок `runLintGaSteps`.
|
|
152
|
+
- `../../../scripts/utils/resolve-cmd.mjs` — `resolveCmd(name): string | null`. Pure-resolve бінарника у `PATH` (без спавну).
|
|
153
|
+
- `../../../scripts/lib/run-lint-step.mjs` — `runLintStep(label, cmd, args): number`. Стандартизований обгортковий спавн одного кроку lint-у з консистентним логом і exit-code-семантикою.
|
|
154
|
+
- `../../../scripts/lib/run-standard-lint.mjs` — `runStandardLint(dirname, fn): Promise<number>`. Канонічна серіалізація lint-команди (lock-файл, тривалість, sentry-style cleanup). Згідно з `.cursor/rules/scripts.mdc` (секція «Серіалізація важких CLI-команд»), цей хелпер заміняє прямий `withLock` у lint-обгортках.
|
|
155
|
+
- `../../../scripts/lib/ensure-tool.mjs` — `ensureTool(name): void`. Перевіряє наявність бінарника в `PATH` і автоматично встановлює його через відповідний менеджер пакетів per-platform (brew/scoop/GitHub Release). Кидає виняток на нездатність встановити.
|
|
156
|
+
|
|
157
|
+
### Зовнішні CLI-інструменти (запускаються в рантаймі)
|
|
158
|
+
|
|
159
|
+
- `shellcheck` — авто-install через `ensureTool`. Потрібен для shell-перевірок у `run:` блоках, які виконує `actionlint`.
|
|
160
|
+
- `conftest` — авто-install через `ensureTool`. Використовується **всередині** `checkGa()` для виконання Rego-полісі з `npm/policy/ga/`.
|
|
161
|
+
- `uv` / `uvx` — hint-only preflight. Потрібен для запуску `uvx zizmor`.
|
|
162
|
+
- `bunx` / `github-actionlint` — виконується через `runLintStep('actionlint', 'bunx', ['github-actionlint'])`.
|
|
163
|
+
- `uvx` / `zizmor` — виконується через `runLintStep('zizmor', 'uvx', ['zizmor', '--offline', '--collect=workflows', '.'])`.
|
|
164
|
+
|
|
165
|
+
## Потік виконання / Використання
|
|
166
|
+
|
|
167
|
+
### Інтеграція в CLI
|
|
168
|
+
|
|
169
|
+
Модуль експортує `runLintGaCli`, яку імпортує `bin/n-cursor.js` як обробник підкоманди:
|
|
170
|
+
|
|
171
|
+
```
|
|
172
|
+
npx @nitra/cursor lint-ga
|
|
173
|
+
# або
|
|
174
|
+
bun lint-ga
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
### Сценарій типового запуску (happy path)
|
|
178
|
+
|
|
179
|
+
1. `runLintGaCli()` → викликає `runStandardLint(import.meta.dirname, runLintGaSteps)` — отримується lock на `npm/rules/ga/lint/`, починається timing.
|
|
180
|
+
2. Усередині `runLintGaSteps`:
|
|
181
|
+
- `ensureTool('shellcheck')` — якщо нема, авто-встановлення (brew/scoop/release).
|
|
182
|
+
- `ensureTool('conftest')` — те саме.
|
|
183
|
+
- `preflight(UV_PREFLIGHT)` — друкує `✅ uv знайдено в PATH — uvx zizmor запуститься`.
|
|
184
|
+
- `runLintStep('actionlint', 'bunx', ['github-actionlint'])` — exit `0`.
|
|
185
|
+
- `runLintStep('zizmor', 'uvx', ['zizmor', '--offline', '--collect=workflows', '.'])` — exit `0`.
|
|
186
|
+
- Лог `▶ check-ga (rego-полісі npm/policy/ga/ + JS cross-file перевірки)`.
|
|
187
|
+
- `await checkGa()` — повертає `0`.
|
|
188
|
+
3. `runStandardLint` логує загальну тривалість, знімає lock і повертає `0`.
|
|
189
|
+
|
|
190
|
+
### Сценарії з falure
|
|
191
|
+
|
|
192
|
+
- `shellcheck` або `conftest` не встановлено й `ensureTool` не зміг встановити — виняток пробивається крізь `runLintGaSteps`, `runStandardLint` ловить його та конвертує у `exit 1`.
|
|
193
|
+
- `uv` відсутній — `preflight(UV_PREFLIGHT)` друкує hint, `runLintGaSteps` повертає `1`, наступні кроки не виконуються.
|
|
194
|
+
- `actionlint` повертає не-нульовий код — `runLintGaSteps` повертає цей код, `zizmor` і `checkGa()` не запускаються.
|
|
195
|
+
- `zizmor` повертає не-нульовий код — те саме: одразу повертається його exit-code.
|
|
196
|
+
- `checkGa()` повертає не-нульовий код — він і є фінальним результатом `runLintGaCli`.
|
|
197
|
+
|
|
198
|
+
### Контракт «суперсет `check ga`»
|
|
199
|
+
|
|
200
|
+
Оскільки фінальний крок `runLintGaSteps` — `checkGa()` (та сама `check`-функція з `../js/workflows.mjs`, що використовується підкомандою `npx @nitra/cursor check ga`), `lint-ga` є суперсетом цієї перевірки: він додає `actionlint` (синтаксис) і `zizmor` (security-аудит) перед `check`. Це усуває потребу запускати `check ga` окремо в pipeline-ах, що вже виконують `lint-ga`.
|
|
201
|
+
|
|
202
|
+
### Канон патерну `lint-*`
|
|
203
|
+
|
|
204
|
+
Файл сповідує канон патерну `lint-*` із `.cursor/rules/scripts.mdc` (секція «Серіалізація важких CLI-команд»):
|
|
205
|
+
|
|
206
|
+
- Серіалізація — через `runStandardLint`, **не** через прямий `withLock`.
|
|
207
|
+
- Кожна стадія — через `runLintStep` (узгоджений лог-формат, semantic exit-codes).
|
|
208
|
+
- Експортована функція має назву `run<Name>Cli` (тут — `runLintGaCli`).
|
|
209
|
+
- Фінальна делегація бізнес-частини — у відповідний `rules/<name>/fix.mjs::check()`, щоб бути одним джерелом істини з `npx @nitra/cursor check <name>`.
|
|
@@ -96,9 +96,9 @@ deny contains msg if {
|
|
|
96
96
|
}
|
|
97
97
|
|
|
98
98
|
# YAML 1.1 quirk: `dry_run: no` парситься як boolean false у Go-yaml (conftest).
|
|
99
|
-
# Template (від `yaml` npm)
|
|
99
|
+
# Template (від `yaml` npm) читає `no` як рядок, тому нормалізуємо обидві форми.
|
|
100
100
|
deny contains msg if {
|
|
101
|
-
step0.with.dry_run != expected_step0.with.dry_run # noqa: rules-style-no-equality-with-false
|
|
101
|
+
normalize_dry_run(step0.with.dry_run) != normalize_dry_run(expected_step0.with.dry_run) # noqa: rules-style-no-equality-with-false
|
|
102
102
|
msg := "clean-merged-branch.yml: with.dry_run має бути no (ga.mdc)"
|
|
103
103
|
}
|
|
104
104
|
|
|
@@ -139,3 +139,12 @@ echo_deleted_branches if {
|
|
|
139
139
|
contains(step1.run, "Deleted branches:")
|
|
140
140
|
contains(step1.run, "${DELETED_BRANCHES}")
|
|
141
141
|
}
|
|
142
|
+
|
|
143
|
+
normalize_dry_run(false) := false
|
|
144
|
+
|
|
145
|
+
normalize_dry_run(value) := false if lower(sprintf("%v", [value])) == "no"
|
|
146
|
+
|
|
147
|
+
normalize_dry_run(value) := value if {
|
|
148
|
+
value != false # noqa: equals-pattern-matching
|
|
149
|
+
lower(sprintf("%v", [value])) != "no"
|
|
150
|
+
}
|
|
@@ -26,10 +26,9 @@ jobs:
|
|
|
26
26
|
github_token: ${{ github.token }}
|
|
27
27
|
last_commit_age_days: 90
|
|
28
28
|
ignore_branches: main,dev
|
|
29
|
-
#
|
|
30
|
-
#
|
|
31
|
-
|
|
32
|
-
dry_run: false
|
|
29
|
+
# Action CLI accepts only yes/no. Go-yaml in conftest parses `no` as
|
|
30
|
+
# boolean false, so the Rego policy normalizes both forms.
|
|
31
|
+
dry_run: no
|
|
33
32
|
|
|
34
33
|
- name: Get output
|
|
35
34
|
env:
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
# `npm/rules/graphql/fix.mjs`
|
|
2
|
+
|
|
3
|
+
## Огляд
|
|
4
|
+
|
|
5
|
+
Файл є точкою входу до правила `graphql` у складі CLI-інструмента `@nitra/cursor`. Він поєднує дві ролі:
|
|
6
|
+
|
|
7
|
+
1. **Library mode** — експортує функцію `run(ctx)`, яку зовнішня CLI-оркестрація викликає через `import + run(ctx)` як частину пакетного прогону всіх правил.
|
|
8
|
+
2. **Standalone mode** — якщо файл запущено напряму (`bun rules/graphql/fix.mjs`), виконується повний еквівалент команди `npx @nitra/cursor fix graphql` із завантаженням конфігурації, whitelist та підсумком (summary).
|
|
9
|
+
|
|
10
|
+
Сама логіка перевірки винесена у спільний helper `runStandardRule`, тобто `fix.mjs` для правила `graphql` — це тонкий wrapper, який лише прив'язує спільну механіку до конкретної директорії правила (через `import.meta.dirname`). Послідовність перевірки, що виконується в результаті: `applies → JS-concerns → policy → mdc-refs`.
|
|
11
|
+
|
|
12
|
+
Файл є частиною стандартизованої конвенції правил `npm/rules/<id>/fix.mjs`, де `<id>` — ідентифікатор правила (тут `graphql`).
|
|
13
|
+
|
|
14
|
+
## Експорти / API
|
|
15
|
+
|
|
16
|
+
| Експорт | Тип | Призначення |
|
|
17
|
+
| ------- | --------------------------------- | ----------------------------------------------------------------------------------------------------------- |
|
|
18
|
+
| `run` | `function(ctx?): Promise<number>` | Named export — library entry-point правила. Викликається оркестратором, який пакетно запускає набір правил. |
|
|
19
|
+
|
|
20
|
+
Default export відсутній. Інших named-експортів файл не визначає.
|
|
21
|
+
|
|
22
|
+
Окремий top-level `if`-блок наприкінці файла активує standalone-режим — він не є експортом, а виконується як side-effect модуля при прямому запуску.
|
|
23
|
+
|
|
24
|
+
## Функції
|
|
25
|
+
|
|
26
|
+
### `run(ctx)`
|
|
27
|
+
|
|
28
|
+
```js
|
|
29
|
+
export function run(ctx) {
|
|
30
|
+
return runStandardRule(import.meta.dirname, ctx)
|
|
31
|
+
}
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
**Призначення.** Library-обгортка над `runStandardRule`, що запускає стандартний пайплайн правила `graphql`: `applies → JS-concerns → policy → mdc-refs`. Конкретні фази (підбір файлів, перевірка JS, policy-правила, перевірка mdc-посилань) реалізовані у спільному helper; `fix.mjs` тільки повідомляє, _яке саме_ правило виконувати, — через шлях до своєї директорії (`import.meta.dirname`), де лежать `meta.json`, `*.mdc`, підтеки `js/`, `policy/`, `lib/` тощо.
|
|
35
|
+
|
|
36
|
+
**Параметри.**
|
|
37
|
+
|
|
38
|
+
| Параметр | Тип | Обов'язковий | Опис |
|
|
39
|
+
| -------- | ----------------------------------------------------------- | ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
40
|
+
| `ctx` | `RuleContext` (з `../../scripts/lib/run-standard-rule.mjs`) | Ні | Контекст прогону. Передається оркестратором для перевикористання ресурсів між правилами (наприклад, `walkCache` — кеш обходу файлової системи, аби не сканувати дерево заново для кожного правила). Якщо `ctx` не передано, `runStandardRule` працює зі своїм дефолтним станом. |
|
|
41
|
+
|
|
42
|
+
**Повертає.** `Promise<number>` — exit-code прогону правила:
|
|
43
|
+
|
|
44
|
+
- `0` — правило пройшло без порушень (OK).
|
|
45
|
+
- `1` — виявлено порушення (правило фейлиться).
|
|
46
|
+
|
|
47
|
+
**Side effects.** Сам по собі `run` не має побічних ефектів у файлі — повертає `Promise`, отриманий від `runStandardRule`. Усі реальні ефекти (читання FS, друк діагностики у stdout/stderr, оновлення кешу в `ctx`) інкапсульовані в `runStandardRule`. Зокрема, у library-режимі функція **не** викликає `process.exit` — управління exit-кодом лежить на оркестраторі.
|
|
48
|
+
|
|
49
|
+
### Standalone-блок (top-level `if`)
|
|
50
|
+
|
|
51
|
+
```js
|
|
52
|
+
if (isRunAsCli(import.meta.url)) {
|
|
53
|
+
// eslint-disable-next-line n/no-process-exit, unicorn/no-process-exit -- standalone entry-point має повертати exit-code для CI/IDE
|
|
54
|
+
process.exit(await runRuleCli(import.meta.dirname))
|
|
55
|
+
}
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
Це не функція, а top-level side-effect модуля. Виконується одноразово при завантаженні.
|
|
59
|
+
|
|
60
|
+
**Умова активації.** `isRunAsCli(import.meta.url)` повертає `true`, коли модуль завантажений як точка входу (тобто шлях файла збігається з тим, що передано Node/Bun у `process.argv`), а не імпортований як бібліотека.
|
|
61
|
+
|
|
62
|
+
**Дія.** Викликає `runRuleCli(import.meta.dirname)` — повний CLI-флоу одного правила (config-loading, whitelist, summary) — і завершує процес його exit-кодом через `process.exit`. Це робить файл прямим аналогом виклику `npx @nitra/cursor fix graphql`.
|
|
63
|
+
|
|
64
|
+
**Чому `process.exit` явний.** Standalone entry-point має повернути коректний exit-code для CI/IDE-інтеграції, тому два правила ESLint (`n/no-process-exit`, `unicorn/no-process-exit`) свідомо вимкнено для цього рядка коментарем-обґрунтуванням.
|
|
65
|
+
|
|
66
|
+
**Чому `await` на top-level.** Файл використовує top-level `await` — це валідно для ESM-модулів. `runRuleCli` повертає `Promise<number>`, і його результат потрібен синхронно як аргумент `process.exit`.
|
|
67
|
+
|
|
68
|
+
## Залежності
|
|
69
|
+
|
|
70
|
+
### Внутрішні (відносні)
|
|
71
|
+
|
|
72
|
+
| Модуль | Імпорт | Роль |
|
|
73
|
+
| ----------------------------------------- | -------------------------- | --------------------------------------------------------------------------------------------------------- |
|
|
74
|
+
| `../../scripts/lib/run-rule-cli.mjs` | `isRunAsCli`, `runRuleCli` | Інфраструктура standalone-режиму: визначення, чи файл запущено як CLI, та повний CLI-флоу одного правила. |
|
|
75
|
+
| `../../scripts/lib/run-standard-rule.mjs` | `runStandardRule` | Стандартний пайплайн правила (`applies → JS-concerns → policy → mdc-refs`) і тип `RuleContext`. |
|
|
76
|
+
|
|
77
|
+
Імпорти відносні, бо `fix.mjs` лежить у `npm/rules/graphql/`, а спільні helpers — у `npm/scripts/lib/`. Два рівні `..` піднімають із `rules/graphql/` до `npm/` і потім спускають у `scripts/lib/`.
|
|
78
|
+
|
|
79
|
+
### Зовнішні
|
|
80
|
+
|
|
81
|
+
Прямих зовнішніх (npm) залежностей файл не оголошує. Будь-які зовнішні пакети підтягуються транзитивно через `runStandardRule` / `runRuleCli`.
|
|
82
|
+
|
|
83
|
+
### Платформенні / рантайм
|
|
84
|
+
|
|
85
|
+
- **ES Modules** — файл використовує синтаксис ESM (`import`, `export`), top-level `await`, `import.meta.url`, `import.meta.dirname`.
|
|
86
|
+
- **`import.meta.dirname`** — доступне у сучасних Node.js (>= 20.11) та Bun. Повертає абсолютний шлях до директорії модуля; використовується як ідентифікатор правила для helpers.
|
|
87
|
+
- **`process.exit`** — Node.js/Bun API; завершує процес із заданим exit-кодом.
|
|
88
|
+
|
|
89
|
+
## Потік виконання / Використання
|
|
90
|
+
|
|
91
|
+
### Library mode (оркестрація)
|
|
92
|
+
|
|
93
|
+
1. Зовнішній код (CLI-оркестратор `@nitra/cursor`) робить `import { run } from '<...>/rules/graphql/fix.mjs'`.
|
|
94
|
+
2. Оркестратор готує `ctx` (наприклад, спільний `walkCache`) і викликає `await run(ctx)`.
|
|
95
|
+
3. `run` делегує виклик у `runStandardRule(import.meta.dirname, ctx)`. Helper, маючи шлях до директорії правила, читає її `meta.json`, `*.mdc`, підтеки `js/`, `policy/` і виконує стандартний пайплайн.
|
|
96
|
+
4. Повертається `0` або `1`. Оркестратор агрегує коди всіх правил у фінальний exit-status.
|
|
97
|
+
|
|
98
|
+
У цьому режимі `process.exit` **не** викликається — модуль не завершує процес самостійно.
|
|
99
|
+
|
|
100
|
+
### Standalone mode (пряма CLI)
|
|
101
|
+
|
|
102
|
+
1. Користувач запускає `bun npm/rules/graphql/fix.mjs` (або шлях через рантайм).
|
|
103
|
+
2. ESM-модуль завантажується. Виконується `isRunAsCli(import.meta.url)` — повертає `true`.
|
|
104
|
+
3. Викликається `await runRuleCli(import.meta.dirname)` — повний CLI-флоу (config, whitelist, summary).
|
|
105
|
+
4. `process.exit(<code>)` завершує процес. Code приходить у CI/IDE як результат прогону правила.
|
|
106
|
+
|
|
107
|
+
Цей режим повністю еквівалентний `npx @nitra/cursor fix graphql` і існує, щоб правило можна було запустити ізольовано — для дебагу або інтеграції з IDE-таском без участі оркестратора.
|
|
108
|
+
|
|
109
|
+
### Дві ролі в одному файлі
|
|
110
|
+
|
|
111
|
+
Подвійна роль (library `run` + standalone `main`) дозволяє:
|
|
112
|
+
|
|
113
|
+
- **Перевикористовувати** код пайплайна — і оркестратор, і пряма CLI йдуть через однакову логіку `runStandardRule` / `runRuleCli`.
|
|
114
|
+
- **Дотримуватися конвенції** `npm/rules/<id>/fix.mjs`: усі правила мають однакову структуру entry-файла, тому інструменти (IDE-завдання, скрипти scaffold) можуть запускати будь-яке правило за єдиним шляхом.
|
|
115
|
+
|
|
116
|
+
### Розширення
|
|
117
|
+
|
|
118
|
+
Щоб додати своєрідну поведінку правила `graphql`, не треба змінювати `fix.mjs` — достатньо покласти відповідні файли в директорію правила:
|
|
119
|
+
|
|
120
|
+
- `meta.json` — метадані (id, опис).
|
|
121
|
+
- `graphql.mdc` — людиночитна частина правила.
|
|
122
|
+
- `js/` — JS-перевірки (фаза JS-concerns).
|
|
123
|
+
- `policy/` — policy-перевірки.
|
|
124
|
+
- `lib/` — спільний код правила.
|
|
125
|
+
|
|
126
|
+
`runStandardRule` сам підбере й виконає те, що знайде в директорії. `fix.mjs` залишається тонким wrapper-ом.
|