@nitra/cursor 1.13.76 → 1.13.83
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/CHANGELOG.md +89 -0
- package/README.md +5 -5
- package/bin/n-cursor.js +16 -21
- package/package.json +1 -1
- package/rules/abie/abie.mdc +12 -4
- package/rules/abie/fix.mjs +15 -0
- package/rules/abie/policy/base_deployment_preem/base_deployment_preem.rego +9 -11
- package/rules/abie/policy/health_check_policy/health_check_policy.rego +9 -10
- package/rules/abie/policy/http_route_base/http_route_base.rego +7 -8
- package/rules/abie/utils/k8s-tree.mjs +1 -1
- package/rules/adr/adr.mdc +1 -1
- package/rules/adr/fix.mjs +15 -0
- package/rules/bun/fix.mjs +15 -0
- package/rules/capacitor/fix.mjs +15 -0
- package/rules/changelog/changelog.mdc +1 -1
- package/rules/changelog/fix.mjs +15 -0
- package/rules/changelog/{fix → js}/consistency/check.mjs +16 -16
- package/{scripts/utils → rules/changelog/js/consistency}/package-manifest.mjs +1 -1
- package/rules/ci4/fix.mjs +15 -0
- package/rules/docker/docker.mdc +3 -3
- package/rules/docker/fix.mjs +15 -0
- package/rules/docker/{fix → js}/lint/check.mjs +3 -3
- package/{scripts/utils → rules/docker/js/lint}/docker-hadolint.mjs +3 -3
- package/rules/docker/lint/lint.mjs +2 -2
- package/rules/efes/fix.mjs +15 -0
- package/rules/feedback/fix.mjs +15 -0
- package/rules/ga/fix.mjs +15 -0
- package/rules/ga/lint/lint.mjs +5 -2
- package/rules/graphql/fix.mjs +15 -0
- package/rules/graphql/{fix → js}/tooling/check.mjs +1 -1
- package/{scripts/utils → rules/graphql/js/tooling}/graphql-gql-scan.mjs +47 -12
- package/rules/hasura/fix.mjs +15 -0
- package/rules/hasura/{fix → js}/internal_urls/check.mjs +1 -1
- package/rules/hasura/policy/svc_hl/svc_hl.rego +1 -1
- package/rules/image-avif/fix.mjs +15 -0
- package/rules/image-compress/fix.mjs +15 -0
- package/rules/js-bun-db/fix.mjs +15 -0
- package/{scripts/utils → rules/js-bun-db/js/safety}/bun-sql-scan.mjs +1 -1
- package/rules/js-bun-db/{fix → js}/safety/check.mjs +1 -1
- package/rules/js-bun-redis/fix.mjs +15 -0
- package/rules/js-bun-redis/policy/package_json/package_json.rego +1 -1
- package/rules/js-lint/fix.mjs +15 -0
- package/rules/js-lint/{fix → js}/tooling/check.mjs +3 -15
- package/{scripts/utils → rules/js-lint/js/tooling}/rebuild-oxlint-canonical.mjs +1 -1
- package/rules/js-lint/js-lint.mdc +2 -2
- package/rules/js-mssql/fix.mjs +15 -0
- package/rules/js-mssql/{fix → js}/deps/check.mjs +1 -1
- package/{scripts/utils → rules/js-mssql/js/deps}/mssql-pool-scan.mjs +1 -1
- package/rules/js-run/fix.mjs +15 -0
- package/{scripts/utils → rules/js-run/js/runtime}/bunyan-imports.mjs +1 -1
- package/{scripts/utils → rules/js-run/js/runtime}/check-env-scan.mjs +1 -1
- package/rules/js-run/{fix → js}/runtime/check.mjs +5 -5
- package/{scripts/utils → rules/js-run/js/runtime}/conn-file-rules.mjs +1 -1
- package/{scripts/utils → rules/js-run/js/runtime}/conn-imports-scan.mjs +1 -1
- package/{scripts/utils → rules/js-run/js/runtime}/promise-settimeout-scan.mjs +1 -1
- package/rules/k8s/fix.mjs +15 -0
- package/rules/k8s/k8s.mdc +2 -2
- package/rules/nginx-default-tpl/fix.mjs +15 -0
- package/rules/nginx-default-tpl/{fix → js}/template/check.mjs +1 -1
- package/rules/npm-module/fix.mjs +15 -0
- package/rules/npm-module/{fix → js}/package_structure/check.mjs +11 -1
- package/rules/php/fix.mjs +15 -0
- package/rules/rego/fix.mjs +15 -0
- package/rules/security/fix.mjs +15 -0
- package/rules/security/security.mdc +2 -2
- package/rules/style-lint/fix.mjs +15 -0
- package/rules/tauri/fix.mjs +15 -0
- package/rules/test/auto.md +1 -0
- package/rules/test/fix.mjs +15 -0
- package/rules/test/js/location/check.mjs +77 -0
- package/rules/test/test.mdc +60 -0
- package/rules/text/fix.mjs +15 -0
- package/rules/vue/fix.mjs +15 -0
- package/rules/vue/{fix → js}/packages/check.mjs +2 -2
- package/rules/vue/vue.mdc +1 -1
- package/scripts/auto-rules.mjs +3 -3
- package/scripts/sync-claude-config.mjs +2 -2
- package/scripts/utils/ast-scan-utils.mjs +3 -2
- package/scripts/utils/discover-checkable-rules.mjs +30 -18
- package/scripts/utils/list-rule-ids.mjs +23 -0
- package/scripts/utils/run-rule.mjs +7 -7
- package/scripts/utils/run-standard-rule.mjs +34 -0
- package/scripts/utils/walk-cache.mjs +24 -0
- package/scripts/utils/with-lock.mjs +120 -0
- package/scripts/utils/workspaces.mjs +1 -1
- package/scripts/utils/worktree-fingerprint.mjs +30 -0
- /package/rules/abie/{fix → js}/applies/check.mjs +0 -0
- /package/rules/abie/{fix → js}/env_dns/check.mjs +0 -0
- /package/rules/abie/{fix → js}/firebase_hosting/check.mjs +0 -0
- /package/rules/abie/{fix → js}/hc_pairing/check.mjs +0 -0
- /package/rules/abie/{fix → js}/ua_http_route/check.mjs +0 -0
- /package/rules/abie/{fix → js}/ua_node_selector/check.mjs +0 -0
- /package/rules/adr/{fix → js}/hooks/check.mjs +0 -0
- /package/rules/adr/{fix → js}/hooks/template/.gitignore.snippet +0 -0
- /package/rules/bun/{fix → js}/layout/check.mjs +0 -0
- /package/rules/capacitor/{fix → js}/platforms/check.mjs +0 -0
- /package/{scripts/utils → rules/docker/js/lint}/docker-mirror.mjs +0 -0
- /package/rules/ga/{fix → js}/workflows/check.mjs +0 -0
- /package/rules/image-avif/{fix → js}/avif_generation/check.mjs +0 -0
- /package/rules/image-compress/{fix → js}/package_setup/check.mjs +0 -0
- /package/rules/js-bun-redis/{fix → js}/imports/check.mjs +0 -0
- /package/{scripts/utils → rules/js-lint/js/tooling}/knip-canonical.json +0 -0
- /package/{scripts/utils → rules/js-lint/js/tooling}/oxlint-canonical-skeleton.json +0 -0
- /package/{scripts/utils → rules/js-lint/js/tooling}/oxlint-canonical.json +0 -0
- /package/{scripts/utils → rules/js-lint/js/tooling}/oxlint-rules.tsv +0 -0
- /package/rules/k8s/{fix → js}/kubescape_exceptions/template/.kubescape-exceptions.json.snippet.json +0 -0
- /package/rules/k8s/{fix → js}/manifests/check.mjs +0 -0
- /package/rules/php/{fix → js}/tooling/check.mjs +0 -0
- /package/rules/rego/{fix → js}/applies/check.mjs +0 -0
- /package/rules/security/{fix → js}/sample_secret/check.mjs +0 -0
- /package/rules/security/{fix → js}/trufflehog/check.mjs +0 -0
- /package/rules/security/{fix → js}/trufflehog/template/.trufflehog-exclude.snippet.txt +0 -0
- /package/rules/style-lint/{fix → js}/tooling/check.mjs +0 -0
- /package/rules/tauri/{fix → js}/tooling/check.mjs +0 -0
- /package/rules/text/{fix → js}/formatting/check.mjs +0 -0
- /package/{scripts/utils → rules/vue/js/packages}/vue-forbidden-imports.mjs +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,95 @@
|
|
|
4
4
|
|
|
5
5
|
Формат — [Keep a Changelog](https://keepachangelog.com/uk/1.1.0/), нумерація — [SemVer](https://semver.org/lang/uk/).
|
|
6
6
|
|
|
7
|
+
## [1.13.83] - 2026-05-23
|
|
8
|
+
|
|
9
|
+
### Changed
|
|
10
|
+
|
|
11
|
+
- **Per-rule `fix.mjs` entry-point + rename `fix/` → `js/`:** кожне з 30 правил тепер має `rules/<id>/fix.mjs` — 11-рядковий wrapper над новим `runStandardRule`. CLI більше не робить convention-based discovery на верхньому рівні — перебирає правила через `listRuleIds` і викликає `await import(rules/<id>/fix.mjs).run({ walkCache })`. Каталог `fix/<concern>/` перейменовано на `js/<concern>/` для усунення колізії з кореневим `fix.mjs` та узгодження з `policy/` (за технологією, не функцією).
|
|
12
|
+
- **Локальна логіка в `fix.mjs` заборонена** — розширення поведінки правил тільки через опції в `RuleContext` (зараз: `walkCache`; зарезервовано на майбутнє: `skipMdcRefs`, `skipApplies`, `onlyConcerns`). Простір варіацій повністю описано в `RuleContext` JSDoc; convention-drift виключений на рівні дизайну.
|
|
13
|
+
- **Shared `walkCache`** як module-level singleton у `scripts/utils/walk-cache.mjs` (`getOrCreateWalkCache` + `resetWalkCache` для тестів). CLI створює один cache на прогон і прокидає через ctx до всіх concerns.
|
|
14
|
+
- **Нові utils:** `scripts/utils/run-standard-rule.mjs`, `scripts/utils/list-rule-ids.mjs`, `scripts/utils/walk-cache.mjs`. Експорт `discoverOneRule(ruleDir, ruleId)` з `discover-checkable-rules.mjs` (виокремлено з існуючого `discoverCheckableRules` — DRY).
|
|
15
|
+
- **Нові тести:** `tests/fix-mjs-contract.test.mjs` (91 кейс — smoke на всі 30 правил), `tests/run-standard-rule.test.mjs`, `tests/list-rule-ids.test.mjs`, `tests/walk-cache.test.mjs`, `tests/discover-one-rule.test.mjs`. Існуючі тести оновлено в частині import-шляхів `/fix/<concern>` → `/js/<concern>` (логіка не змінювалась); видалено застарілий `discoverCheckableRules > legacy js/-структура ігнорується` — `js/` тепер canonical convention.
|
|
16
|
+
|
|
17
|
+
### Breaking
|
|
18
|
+
|
|
19
|
+
- **Для зовнішніх інтеграторів, що пишуть власні правила:** каталог `rules/<id>/fix/<concern>/check.mjs` перейменовано на `rules/<id>/js/<concern>/check.mjs`; додатково потрібен файл `rules/<id>/fix.mjs` з канонічним вмістом (див. будь-яке вбудоване правило для шаблону). CLI більше не запустить правило без `fix.mjs`.
|
|
20
|
+
|
|
21
|
+
### Notes
|
|
22
|
+
|
|
23
|
+
- Зворотна сумісність CLI: `npx @nitra/cursor check` та `npx @nitra/cursor check abie` працюють як раніше.
|
|
24
|
+
- Use-cases: `bun npm/rules/abie/fix.mjs` (debug); `bun npm/rules/${{ matrix.rule }}/fix.mjs` (CI per-rule jobs); IDE Run-button на `fix.mjs`.
|
|
25
|
+
|
|
26
|
+
## [1.13.82] - 2026-05-23
|
|
27
|
+
|
|
28
|
+
### Changed
|
|
29
|
+
|
|
30
|
+
- **`rules/test`: виняток для `*_test.rego` файлів — лишаються поряд із полісі (OPA/Conftest community-конвенція)**:
|
|
31
|
+
- **Rego unit-тести (`*_test.rego`) лежать у тому самому каталозі, що й `<name>.rego`** — за загальноприйнятим патерном OPA/Conftest. `package <name>` (полісі) ↔ `package <name>_test` (тест) семантично зв'язані через `package`-декларації, а не локацію файлу; `conftest verify -p <dir>` рекурсивний, тож знаходить тест незалежно від місця, але спільнота тримає їх поруч (бачимо у OPA examples, Gatekeeper library, Datree, Styra DAS bundles). Це **легітимне відхилення** від внутрішньої JS-конвенції «`tests/` всюди» на користь OPA-ідіоми.
|
|
32
|
+
- `rules/test/test.mdc` v1.1 — додано **окрему секцію про виняток** для Rego: «`*_test.rego` лишаються поряд із полісі, бо це загальноприйнятий OPA/Conftest community-патерн» (з прикладом структури `policy/<concern>/{<name>.rego, <name>_test.rego, target.json}`).
|
|
33
|
+
- `rules/test/fix/location/check.mjs` — перевіряє **лише `*.test.mjs`**, `*_test.rego` свідомо виключено з область перевірки (зафіксовано у docstring).
|
|
34
|
+
- Додано test-case у `rules/test/fix/location/tests/check.test.mjs`: `*_test.rego` поряд із полісі НЕ є порушенням.
|
|
35
|
+
- **Відкат переміщення `*_test.rego`**: 69 файлів, які раніше було помилково перенесено у `policy/<concern>/tests/<name>_test.rego`, повернуто у `policy/<concern>/<name>_test.rego` через `git mv`. Порожні `tests/` піддиректорії під `policy/` видалено.
|
|
36
|
+
- **`npx @nitra/cursor check test`** охоплює лише JS-тести: «✅ Всі 77 файлів *.test.mjs у каталозі tests/». Rego-тести продовжують перевірятись через `conftest verify` у правилі `rego`.
|
|
37
|
+
|
|
38
|
+
## [1.13.81] - 2026-05-23
|
|
39
|
+
|
|
40
|
+
### Fixed
|
|
41
|
+
|
|
42
|
+
- **`npm-module.package_structure`: carve-out для rule-name сегмента** у `classifyPublishedFileAsTest`. Раніше для шляху `rules/<X>/...` сегмент `<X>` піддавався TEST_DIR_NAMES-перевірці, що давало false positive на правилах із id, що збігається з test-style ім'ям (`test`, `tests`, `fixtures` тощо). Тепер сегмент індекс 1 (ім'я правила, коли індекс 0 — `rules`) пропускається; глибші сегменти (`rules/<r>/fix/<c>/tests/`) продовжують перевірятись.
|
|
43
|
+
|
|
44
|
+
### Added
|
|
45
|
+
|
|
46
|
+
- **Нове правило `test` (`npm/rules/test/`)** — програмний канон розміщення тестів (ADR `docs/adr/20260523-154806-...`):
|
|
47
|
+
- `test.mdc` — конвенція «`*.test.mjs` живуть у `tests/` поряд із джерелом», з описом спецвипадків (root `tests/`, fixtures у `tests/__fixtures__/` і `tests/fixtures/`, test-helpers як shared-infra).
|
|
48
|
+
- `fix/location/check.mjs` — обхід дерева `walkDir`'ом (зі стандартним skip-листом + `.n-cursor.json:ignore`); для кожного `*.test.mjs` басенейм батьківської директорії має бути `tests`, інакше fail з вказівкою куди перенести.
|
|
49
|
+
- `fix/location/tests/check.test.mjs` — 6 тестів самого правила (eats own dogfood).
|
|
50
|
+
- `auto.md` — auto-enable умова: «якщо у проекті є хоча б один файл `*.test.mjs`».
|
|
51
|
+
- Додано `"test"` у `.n-cursor.json:rules` репо `@nitra/cursor`.
|
|
52
|
+
- Додано `"ignore": [".claude/worktrees"]` у `.n-cursor.json` — щоб правило не звітувало про знімки в git worktrees.
|
|
53
|
+
|
|
54
|
+
### Changed
|
|
55
|
+
|
|
56
|
+
- **Тести переміщено з-поряд-із-файлом у `dir/tests/` піддиректорію** (ADR `docs/adr/20260523-154806-...`):
|
|
57
|
+
- **73 sibling-тести** у `rules/...` і `scripts/...`: для кожного `dir/X.test.mjs` → `dir/tests/X.test.mjs` із автоматичним оновленням relative imports.
|
|
58
|
+
- **3 integration-тести у `npm/tests/`** — без змін (вже відповідали конвенції).
|
|
59
|
+
- **`npm/scripts/utils/__fixtures__/`** → `npm/scripts/utils/tests/__fixtures__/`.
|
|
60
|
+
- **`npm/rules/nginx-default-tpl/fix/template/fixtures/`** → `.../tests/fixtures/`; посилання в `npm/tests/check-rule-fixtures.test.mjs` оновлено.
|
|
61
|
+
- Ручні фіксапи 4 тестів із HERE/`..` path patterns (sync-setup-bun-deps-action, inline-template-links, rules/adr/fix/hooks, rules/abie/utils/enabled) — додано додатковий `..`, бо тести стали на рівень глибше.
|
|
62
|
+
- `package.json#files` негативні globs (`!**/*.test.mjs`, `!**/__fixtures__/**`, `!**/fixtures/**`) працюють рекурсивно — без змін.
|
|
63
|
+
- **77 тестів** проходять у новому layout (76 існуючих + 1 нового правила): `bun test` 843 pass / 2 fail (обидва — pre-existing `with-lock` issues, не пов'язані).
|
|
64
|
+
- `npx @nitra/cursor check test` → `✅ Всі 77 файлів *.test.mjs у каталозі tests/ (test.mdc)`.
|
|
65
|
+
|
|
66
|
+
## [1.13.79] - 2026-05-23
|
|
67
|
+
|
|
68
|
+
### Changed
|
|
69
|
+
|
|
70
|
+
- **Перенесення single-rule сканерів і canonical-конфігів з `npm/scripts/utils/` у `npm/rules/<rule>/fix/<sub>/`** (узгоджено з конвенцією `rules/ga/fix/workflows/`, `rules/nginx-default-tpl/fix/template/` тощо; ADR `docs/adr/20260523-114913-...`, який supersede `20260523-112217-...`):
|
|
71
|
+
- **js-lint** (`rules/js-lint/fix/tooling/`): `knip-canonical.json`, `oxlint-canonical.json`, `oxlint-canonical-skeleton.json`, `oxlint-rules.tsv`, `rebuild-oxlint-canonical.mjs`. Константи `OXLINT_CANONICAL_JSON_PATH` / `KNIP_CANONICAL_JSON_PATH` у `check.mjs` стали локальними (без 4-річневих `..`).
|
|
72
|
+
- **js-run** (`rules/js-run/fix/runtime/`): `bunyan-imports.mjs` (+test), `check-env-scan.mjs`, `conn-file-rules.mjs` (+test), `conn-imports-scan.mjs` (+test), `promise-settimeout-scan.mjs` (+test).
|
|
73
|
+
- **docker** (`rules/docker/fix/lint/`): `docker-hadolint.mjs` (+test), `docker-mirror.mjs`. `rules/docker/lint/lint.mjs` тепер імпортує з `../fix/lint/docker-hadolint.mjs`.
|
|
74
|
+
- **js-bun-db** (`rules/js-bun-db/fix/safety/`): `bun-sql-scan.mjs`.
|
|
75
|
+
- **js-mssql** (`rules/js-mssql/fix/deps/`): `mssql-pool-scan.mjs`.
|
|
76
|
+
- **changelog** (`rules/changelog/fix/consistency/`): `package-manifest.mjs` (+test).
|
|
77
|
+
- **vue** (`rules/vue/fix/packages/`): `vue-forbidden-imports.mjs` (+test).
|
|
78
|
+
- **graphql** (`rules/graphql/fix/tooling/`): `graphql-gql-scan.mjs`. Cross-rule імпорту немає: `extractVueScriptBlocks`, локалізована `contentForGqlScan` і власні `isGqlScanSourceFile` / `shouldSkipFileForGqlScan` (з власною source-regex і skip-list `.d.ts` / `auto-imports.d.ts` / `components.d.ts`) дубльовані всередині `graphql-gql-scan.mjs` — правила залишаються самодостатніми.
|
|
79
|
+
- **`scripts/auto-rules.mjs`** оновлено: імпорти переадресовано на нові локації трьох сканерів (`bun-sql-scan`, `graphql-gql-scan`, `vue-forbidden-imports`).
|
|
80
|
+
- **`.mdc`-документація** оновлена: `rules/js-lint/js-lint.mdc`, `rules/docker/docker.mdc`, `rules/vue/vue.mdc`, `.cursor/rules/n-js-lint.mdc`, `.cursor/rules/n-vue.mdc` — посилання на нові шляхи canonical-файлів і сканерів.
|
|
81
|
+
|
|
82
|
+
## [1.13.78] - 2026-05-23
|
|
83
|
+
|
|
84
|
+
### Changed
|
|
85
|
+
|
|
86
|
+
- **abie / k8s / hasura — актуалізація посилань на неіснуючий `check-abie.mjs`:** після реструктуризації `rules/abie/` на `fix/<concern>/check.mjs` (+ Rego-пакети у `policy/`) монолітного `check-abie.mjs` більше немає; застарілі посилання в активних `.mdc`/`.rego`/`.mjs` (поза історичним `CHANGELOG.md`) оновлено:
|
|
87
|
+
- `npm/rules/abie/abie.mdc` — три згадки замінено: пер-документна перевірка HTTPRoute base hostnames → Rego `abie.http_route_base`; env-DNS-скан → `fix/env_dns/check.mjs`; cross-file/FS-логіку розбито за концернами (`hc_pairing/`, `ua_http_route/`, `ua_node_selector/`, `env_dns/`, `firebase_hosting/`) з поясненням, що `targetRef.name -hl` cross-check обчислюється з `hcp.metadata.name` у Rego.
|
|
88
|
+
- `npm/rules/abie/policy/{http_route_base,base_deployment_preem,health_check_policy}/*.rego` — у шапках замінено `npm/scripts/check-abie.mjs` на актуальні джерела: cross-file gating через `policy/<pkg>/target.json` (glob), rule-level applies-гейт у `fix/applies/check.mjs`, FS-парність HCP↔Deployment у `fix/hc_pairing/check.mjs`. Прибрано згадки видалених JS-функцій (`validateAbieHcPolicy`, `deploymentDocumentHasAbieBasePreemNodeSelector`).
|
|
89
|
+
- `npm/rules/k8s/k8s.mdc` — рядок про `targetRef -hl` для abie-проєктів вказує на Rego-пакет `abie.health_check_policy` + `abie.mdc` (замість `check-abie.mjs`).
|
|
90
|
+
- `npm/rules/hasura/fix/internal_urls/check.mjs` — у JSDoc згадку `check-abie` замінено на нейтральне «abie-перевірки».
|
|
91
|
+
|
|
92
|
+
### Added
|
|
93
|
+
|
|
94
|
+
- **`with-lock`:** атомарний `mkdirSync`-лок + SHA-256 fingerprint-дедуп для важких команд; пілот — `lint-ga` автоматично серіалізує паралельні запуски та пропускає дублікати при незміненому робочому дереві (TTL 10 хв). Нові модулі: `scripts/utils/worktree-fingerprint.mjs`, `scripts/utils/with-lock.mjs`.
|
|
95
|
+
|
|
7
96
|
## [1.13.76] - 2026-05-22
|
|
8
97
|
|
|
9
98
|
### Added
|
package/README.md
CHANGED
|
@@ -56,7 +56,7 @@
|
|
|
56
56
|
- Рядки в **base**, які змінюються в overlays, позначайте коментарем на рядку (узгоджено в команді), наприклад: `# буде замінено через kustomize`.
|
|
57
57
|
- Після перенесення в **`base`** / overlays **видаляйте** застарілі маніфести та каталоги, які більше не потрібні.
|
|
58
58
|
|
|
59
|
-
Повний текст правил — у **`k8s.mdc`**; programmatic перевірки — у **`npm/rules/k8s/`**: JS-checks у `
|
|
59
|
+
Повний текст правил — у **`k8s.mdc`**; programmatic перевірки — у **`npm/rules/k8s/`**: JS-checks у `js/<concern>/check.mjs`, rego-policies у `policy/<concern>/<name>.rego` (обидва запускаються через `npx @nitra/cursor check k8s`).
|
|
60
60
|
|
|
61
61
|
### v8r і власний каталог схем
|
|
62
62
|
|
|
@@ -109,13 +109,13 @@ npm/
|
|
|
109
109
|
|
|
110
110
|
### Структура одного правила
|
|
111
111
|
|
|
112
|
-
Кожне правило `npm/rules/<id>/` ділиться за **технологією реалізації** на три сиблінги — `
|
|
112
|
+
Кожне правило `npm/rules/<id>/` ділиться за **технологією реалізації** на три сиблінги — `js/`, `lint/`, `policy/`:
|
|
113
113
|
|
|
114
114
|
```
|
|
115
115
|
npm/rules/<id>/
|
|
116
116
|
├── <id>.mdc # текст правила (після синку — .cursor/rules/n-<id>.mdc)
|
|
117
117
|
├── auto.md # умова автоактивації скілу (опційно)
|
|
118
|
-
├──
|
|
118
|
+
├── js/ # JS для `npx @nitra/cursor check`
|
|
119
119
|
│ └── <concern>/
|
|
120
120
|
│ ├── check.mjs # діагностика — повертає список violations
|
|
121
121
|
│ ├── check.test.mjs
|
|
@@ -134,11 +134,11 @@ npm/rules/<id>/
|
|
|
134
134
|
|
|
135
135
|
| Що реалізує | Канал виклику | Куди |
|
|
136
136
|
| ------------------------- | ---------------------------------------------- | ------------------- |
|
|
137
|
-
| JS-діагностика + автофікс | `npx @nitra/cursor check` (fix-канал) | `
|
|
137
|
+
| JS-діагностика + автофікс | `npx @nitra/cursor check` (fix-канал) | `js/<concern>/` |
|
|
138
138
|
| JS-orchestrator лінту | `bun run lint-<id>` через `n-cursor lint-<id>` | `lint/` |
|
|
139
139
|
| Rego-діагностика | `npx @nitra/cursor check` (fix-канал) | `policy/<concern>/` |
|
|
140
140
|
|
|
141
|
-
`
|
|
141
|
+
`js/` і `policy/` обидва живлять fix-канал (`npx @nitra/cursor check` запускає і JS-checks, і rego-policies), але **розділені за технологією**: JS у `js/`, rego у `policy/`. `lint/` тримає лише JS, що оркеструє `bun run lint-<id>`.
|
|
142
142
|
|
|
143
143
|
## AGENTS.md у проєкті користувача
|
|
144
144
|
|
package/bin/n-cursor.js
CHANGED
|
@@ -83,14 +83,14 @@ import {
|
|
|
83
83
|
import { detectAutoSkills } from '../scripts/auto-skills.mjs'
|
|
84
84
|
import { runStopHookCli } from '../scripts/claude-stop-hook.mjs'
|
|
85
85
|
import { discoverCheckRulesFromCursorRules } from '../scripts/utils/discover-check-rules-from-cursor.mjs'
|
|
86
|
-
import {
|
|
86
|
+
import { listRuleIds } from '../scripts/utils/list-rule-ids.mjs'
|
|
87
87
|
import { ensureNitraCursorInRootDevDependencies } from '../scripts/ensure-nitra-cursor-dev-dependencies.mjs'
|
|
88
88
|
import { runLintDocker } from '../rules/docker/lint/lint.mjs'
|
|
89
89
|
import { runLintGaCli } from '../rules/ga/lint/lint.mjs'
|
|
90
90
|
import { runLintK8s } from '../rules/k8s/lint/lint.mjs'
|
|
91
91
|
import { runLintRego } from '../rules/rego/lint/lint.mjs'
|
|
92
92
|
import { runLintTextCli } from '../rules/text/lint/lint.mjs'
|
|
93
|
-
import {
|
|
93
|
+
import { getOrCreateWalkCache } from '../scripts/utils/walk-cache.mjs'
|
|
94
94
|
import { syncClaudeConfig } from '../scripts/sync-claude-config.mjs'
|
|
95
95
|
import { upgradeNitraCursorToLatestAndBunInstall } from '../scripts/upgrade-nitra-cursor-and-install.mjs'
|
|
96
96
|
import { runRenameYamlExtensionsCli } from './rename-yaml-extensions.mjs'
|
|
@@ -973,26 +973,17 @@ function logRemovedManagedItems(title, basePath, names) {
|
|
|
973
973
|
}
|
|
974
974
|
}
|
|
975
975
|
|
|
976
|
-
/**
|
|
977
|
-
* Знаходить правила, для яких є хоча б щось прогонне: JS-концерн у `rules/<id>/fix/<concern>/check*.mjs`
|
|
978
|
-
* або policy-концерн у `rules/<id>/policy/<concern>/target.json`. Делегує у `discoverCheckableRules`
|
|
979
|
-
* — див. `scripts/utils/discover-checkable-rules.mjs`.
|
|
980
|
-
* @returns {import('../scripts/utils/discover-checkable-rules.mjs').CheckableRule[]} опис правил у алфавітному порядку
|
|
981
|
-
*/
|
|
982
|
-
function discoverCheckScripts() {
|
|
983
|
-
return discoverCheckableRules(BUNDLED_RULES_DIR)
|
|
984
|
-
}
|
|
985
|
-
|
|
986
976
|
/**
|
|
987
977
|
* Запускає перевірки: без аргументів — за `*.mdc` у `.cursor/rules/`; з аргументами — лише вказані правила.
|
|
988
|
-
*
|
|
989
|
-
*
|
|
978
|
+
* Перебирає правила через `listRuleIds`, для кожного робить dynamic `import('<rules>/<id>/fix.mjs')`
|
|
979
|
+
* і викликає `mod.run({ walkCache })`. Сам `runChecks` відповідає лише за фільтр id, агрегацію
|
|
980
|
+
* exit-кодів і shared walk-cache на прогон.
|
|
990
981
|
* @param {string[]} requestedRules імена правил; порожній масив — брати з `.cursor/rules/*.mdc`
|
|
991
982
|
* @returns {Promise<void>}
|
|
992
983
|
*/
|
|
993
984
|
async function runChecks(requestedRules) {
|
|
994
|
-
const
|
|
995
|
-
if (
|
|
985
|
+
const available = await listRuleIds(BUNDLED_RULES_DIR)
|
|
986
|
+
if (available.length === 0) {
|
|
996
987
|
console.error('❌ Не знайдено жодного check-скрипта у пакеті')
|
|
997
988
|
throw new Error('No check scripts found')
|
|
998
989
|
}
|
|
@@ -1008,7 +999,6 @@ async function runChecks(requestedRules) {
|
|
|
1008
999
|
}
|
|
1009
1000
|
}
|
|
1010
1001
|
|
|
1011
|
-
const available = allRules.map(r => r.id)
|
|
1012
1002
|
let idsToCheck
|
|
1013
1003
|
if (requestedRules.length > 0) {
|
|
1014
1004
|
idsToCheck = requestedRules
|
|
@@ -1023,7 +1013,7 @@ async function runChecks(requestedRules) {
|
|
|
1023
1013
|
if (idsToCheck.length === 0) {
|
|
1024
1014
|
console.log(
|
|
1025
1015
|
`\n🔍 ${PACKAGE_NAME} check — у ${RULES_DIR}/ немає правил з programmatic перевіркою ` +
|
|
1026
|
-
`(відповідного
|
|
1016
|
+
`(відповідного fix.mjs у пакеті). Нічого не запущено.\n`
|
|
1027
1017
|
)
|
|
1028
1018
|
return
|
|
1029
1019
|
}
|
|
@@ -1038,14 +1028,19 @@ async function runChecks(requestedRules) {
|
|
|
1038
1028
|
|
|
1039
1029
|
console.log(`\n🔍 ${PACKAGE_NAME} check — перевірка правил (${idsToCheck.length})\n`)
|
|
1040
1030
|
|
|
1041
|
-
const ruleMap = new Map(allRules.map(r => [r.id, r]))
|
|
1042
1031
|
/** @type {Map<string, Promise<string[]>>} shared walk-cache (cross-concern, cross-rule у межах одного прогону) */
|
|
1043
|
-
const walkCache =
|
|
1032
|
+
const walkCache = getOrCreateWalkCache()
|
|
1044
1033
|
let totalFailed = 0
|
|
1045
1034
|
|
|
1046
1035
|
for (const id of idsToCheck) {
|
|
1047
1036
|
try {
|
|
1048
|
-
const
|
|
1037
|
+
const fixPath = join(BUNDLED_RULES_DIR, id, 'fix.mjs')
|
|
1038
|
+
// eslint-disable-next-line no-unsanitized/method -- id з whitelist'у listRuleIds (readdir + existsSync), fixPath не з зовнішнього input
|
|
1039
|
+
const mod = await import(fixPath)
|
|
1040
|
+
if (typeof mod.run !== 'function') {
|
|
1041
|
+
throw new TypeError(`${id}: rules/${id}/fix.mjs не експортує run()`)
|
|
1042
|
+
}
|
|
1043
|
+
const code = await mod.run({ walkCache })
|
|
1049
1044
|
if (code !== 0) totalFailed++
|
|
1050
1045
|
} catch (error) {
|
|
1051
1046
|
console.log(` ❌ Помилка виконання: ${error.message}`)
|
package/package.json
CHANGED
package/rules/abie/abie.mdc
CHANGED
|
@@ -36,7 +36,7 @@ spec:
|
|
|
36
36
|
|
|
37
37
|
### HTTPRoute: спільні сервіси **`auth-run-hl`**, **`file-link-hl`**
|
|
38
38
|
|
|
39
|
-
У **HTTPRoute** у шляху з **`…/k8s/base/…`** у **`spec.hostnames`** дозволені лише **`aiml.live`**, **`*.aiml.live`** та інші піддомени **aiml.live** (перевірка
|
|
39
|
+
У **HTTPRoute** у шляху з **`…/k8s/base/…`** у **`spec.hostnames`** дозволені лише **`aiml.live`**, **`*.aiml.live`** та інші піддомени **aiml.live** (перевірка — Rego-пакет **`abie.http_route_base`**, див. розділ нижче).
|
|
40
40
|
|
|
41
41
|
Ці **Service** (headless **`-hl`**) живуть у **базовому** неймспейсі **`dev`**. У маніфесті **HTTPRoute** під **`k8s`** (шар без **`ua/`** — наприклад **`…/k8s/base/hr.yaml`**) для кожного **`backendRefs`** до такого сервісу явно вкажи **`namespace: dev`** і порт **8080**:
|
|
42
42
|
|
|
@@ -133,7 +133,7 @@ KVCMS_URL=http://kvcms-hl.ua-apruv.svc.abie-ua.internal:8080
|
|
|
133
133
|
|
|
134
134
|
`<namespace>` (наприклад `dev-apruv` / `ua-apruv`) — `metadata.name` цільового namespace після kustomize-overlay для відповідного середовища; `<service>` — `metadata.name` headless Service (`-hl`) того сервісу, до якого йде URL.
|
|
135
135
|
|
|
136
|
-
**Перевірка `check
|
|
136
|
+
**Перевірка `js/env_dns/check.mjs`** сканує всі `*.env` файли, basename яких збігається з `dev.env` / `ua.env` (з провідною крапкою чи без), знаходить **усі** internal URL (`http://<svc>.<ns>.svc.<dns>` — як для Hasura-ендпоінта, так і для KVCMS чи будь-якого іншого) і вимагає, щоб для кожного:
|
|
137
137
|
|
|
138
138
|
- DNS-суфікс відповідав env: `abie-dev.internal` / `abie-ua.internal`;
|
|
139
139
|
- namespace починався з `dev-` / `ua-` відповідно.
|
|
@@ -160,7 +160,7 @@ bun add -d @nitra/abie-docs
|
|
|
160
160
|
|
|
161
161
|
## Швидкий gate через conftest (Rego)
|
|
162
162
|
|
|
163
|
-
Підмножину пер-документних правил продубльовано як rego-полісі у **`npm/rules/abie/policy/`** (запускається через **`bun run lint-rego`** для `*_test.rego` юніт-тестів і через **`npx @nitra/cursor check abie`** для прогону по реальних YAML — деталі в **conftest.mdc** / **n-rego.mdc**). JS у **`
|
|
163
|
+
Підмножину пер-документних правил продубльовано як rego-полісі у **`npm/rules/abie/policy/`** (запускається через **`bun run lint-rego`** для `*_test.rego` юніт-тестів і через **`npx @nitra/cursor check abie`** для прогону по реальних YAML — деталі в **conftest.mdc** / **n-rego.mdc**). JS у **`js/<concern>/check.mjs`** authoritative — rego тільки швидкий gate для одиничного маніфеста (зокрема через IDE-розширення `tsandall.opa`).
|
|
164
164
|
|
|
165
165
|
Пакети (директорія в **`npm/policy/abie/`** → namespace → що перевіряє):
|
|
166
166
|
|
|
@@ -170,4 +170,12 @@ bun add -d @nitra/abie-docs
|
|
|
170
170
|
- **`clean_merged_ignore_branches/`** → `abie.clean_merged_ignore_branches` — у workflow `.github/workflows/clean-merged-branch.yml` крок з `uses: phpdocker-io/github-actions-delete-abandoned-branches` має `with.ignore_branches`, що містить токени `dev,ua` (case-insensitive). **Цільові файли:** `.github/workflows/clean-merged-branch.yml`.
|
|
171
171
|
- **`package_json_docs/`** → `abie.package_json_docs` — у кореневому `package.json` `devDependencies` має містити `@nitra/abie-docs` (presence-only, версію не фіксуємо). **Цільові файли:** `package.json`.
|
|
172
172
|
|
|
173
|
-
Cross-file
|
|
173
|
+
Cross-file / FS-логіка лишається у JS-частинах (`js/<concern>/check.mjs`) — Rego не читає файлову систему й не робить cross-document резолюцію:
|
|
174
|
+
|
|
175
|
+
- парність HCP↔Deployment у каталозі та modeline `hc.yaml` — `js/hc_pairing/check.mjs`;
|
|
176
|
+
- валідація ua-overlay JSON6902 patches на HTTPRoute + аналіз cross-namespace `backendRefs` у пакетах — `js/ua_http_route/check.mjs`;
|
|
177
|
+
- ua-overlay JSON6902 patch на `Deployment.nodeSelector` (`preem: false`) — `js/ua_node_selector/check.mjs`;
|
|
178
|
+
- env→cluster DNS (`*.dev.env` / `*.ua.env`) — `js/env_dns/check.mjs`;
|
|
179
|
+
- скан артефактів Firebase Hosting у підкаталогах першого рівня — `js/firebase_hosting/check.mjs`.
|
|
180
|
+
|
|
181
|
+
Точна звірка `targetRef.name` HealthCheckPolicy з суфіксом `-hl` обчислюється з `hcp.metadata.name` і живе у Rego (`abie.health_check_policy`); за конвенцією `hcp.metadata.name` дорівнює `<deployment.name>`, тому окремий cross-file lookup до маніфесту Deployment не потрібен.
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { runStandardRule } from '../../scripts/utils/run-standard-rule.mjs'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Запускає правило: applies → JS-concerns → policy → mdc-refs (через runStandardRule).
|
|
5
|
+
* @param {import('../../scripts/utils/run-standard-rule.mjs').RuleContext} [ctx] контекст прогону (walkCache тощо)
|
|
6
|
+
* @returns {Promise<number>} 0 — OK, 1 — порушення
|
|
7
|
+
*/
|
|
8
|
+
export function run(ctx) {
|
|
9
|
+
return runStandardRule(import.meta.dirname, ctx)
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
if (import.meta.main) {
|
|
13
|
+
// eslint-disable-next-line unicorn/no-process-exit -- standalone entry-point має повертати exit-code для CI/IDE
|
|
14
|
+
process.exit(await run())
|
|
15
|
+
}
|
|
@@ -1,19 +1,17 @@
|
|
|
1
|
-
#
|
|
2
|
-
# `
|
|
3
|
-
#
|
|
4
|
-
#
|
|
5
|
-
#
|
|
6
|
-
# JSON6902-патчем на `preem: false`.
|
|
1
|
+
# Перевірка (abie.mdc): кожен `Deployment` у файлах під `…/k8s/.../base/…` має
|
|
2
|
+
# `spec.template.spec.nodeSelector.preem` зі значенням, що вважається істинним
|
|
3
|
+
# (boolean `true` або рядок `"true"` без урахування регістру). Overlay ua далі
|
|
4
|
+
# підміняє селектор JSON6902-патчем на `preem: false`
|
|
5
|
+
# (див. `js/ua_node_selector/check.mjs`).
|
|
7
6
|
#
|
|
8
7
|
# Запуск (локально, лише для одного base-YAML з Deployment):
|
|
9
8
|
# conftest test path/to/k8s/base/deployment.yaml \
|
|
10
|
-
# -p npm/
|
|
9
|
+
# -p npm/rules/abie/policy/base_deployment_preem \
|
|
11
10
|
# --namespace abie.base_deployment_preem
|
|
12
11
|
#
|
|
13
|
-
#
|
|
14
|
-
#
|
|
15
|
-
# `
|
|
16
|
-
# Cross-file gating (правило `abie` у `.n-cursor.json`, шлях файла) — у JS.
|
|
12
|
+
# Cross-file gating: шлях `…/k8s/.../base/…` фільтрується через
|
|
13
|
+
# `policy/base_deployment_preem/target.json` (glob). Rule-level applies-гейт —
|
|
14
|
+
# `js/applies/check.mjs` (поле `rules` у `.n-cursor.json`).
|
|
17
15
|
#
|
|
18
16
|
# Структура каталогу збігається зі шляхом пакету (regal: directory-package-mismatch).
|
|
19
17
|
# Конвенція проєкту — `import rego.v1` + multi-value `deny contains msg if { … }`
|
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
#
|
|
2
|
-
# `npm/scripts/check-abie.mjs` (abie.mdc).
|
|
1
|
+
# Структурна перевірка `HealthCheckPolicy` (abie.mdc).
|
|
3
2
|
#
|
|
4
3
|
# Запуск (локально):
|
|
5
4
|
# conftest test path/to/k8s/.../hc.yaml \
|
|
6
|
-
# -p npm/
|
|
5
|
+
# -p npm/rules/abie/policy/health_check_policy \
|
|
7
6
|
# --namespace abie.health_check_policy
|
|
8
7
|
#
|
|
9
8
|
# Перевіряє для `kind: HealthCheckPolicy`:
|
|
@@ -14,12 +13,13 @@
|
|
|
14
13
|
# починається з `/`;
|
|
15
14
|
# - `spec.default.config.httpHealthCheck.port: 8080`;
|
|
16
15
|
# - `spec.targetRef.kind: Service`;
|
|
17
|
-
# - `spec.targetRef.name`
|
|
16
|
+
# - `spec.targetRef.name` — `<hcp.metadata.name>-hl` (exact, з нормалізацією
|
|
17
|
+
# суфікса).
|
|
18
18
|
#
|
|
19
|
-
# Cross-file gating
|
|
20
|
-
#
|
|
21
|
-
#
|
|
22
|
-
#
|
|
19
|
+
# Cross-file gating: glob по `hc.yaml` у k8s-дереві — у
|
|
20
|
+
# `policy/health_check_policy/target.json`. FS-парність HCP↔Deployment та
|
|
21
|
+
# modeline `hc.yaml` — `js/hc_pairing/check.mjs`. Rule-level applies-гейт —
|
|
22
|
+
# `js/applies/check.mjs`.
|
|
23
23
|
#
|
|
24
24
|
# Структура каталогу збігається зі шляхом пакету (regal: directory-package-mismatch).
|
|
25
25
|
# Конвенція проєкту — `import rego.v1` + multi-value `deny contains msg if { … }`
|
|
@@ -122,8 +122,7 @@ deny contains msg if {
|
|
|
122
122
|
}
|
|
123
123
|
|
|
124
124
|
# Нормалізація: якщо `metadata.name` уже закінчується на `-hl` — використовуємо
|
|
125
|
-
# як є; інакше додаємо суфікс.
|
|
126
|
-
# у `check-abie.mjs`.
|
|
125
|
+
# як є; інакше додаємо суфікс.
|
|
127
126
|
expected_target_ref_name(name) := name if {
|
|
128
127
|
endswith(name, "-hl")
|
|
129
128
|
} else := concat("", [name, "-hl"])
|
|
@@ -1,15 +1,14 @@
|
|
|
1
|
-
#
|
|
2
|
-
# `
|
|
3
|
-
# `aiml.live` (включно з піддоменами та `*.aiml.live`).
|
|
1
|
+
# Перевірка `HTTPRoute` у шарі `…/k8s/.../base/...` (abie.mdc): дозволені лише
|
|
2
|
+
# hostnames з домену `aiml.live` (включно з піддоменами та `*.aiml.live`).
|
|
4
3
|
#
|
|
5
4
|
# Запуск (локально):
|
|
6
|
-
# conftest test path/to/k8s/base/hr.yaml
|
|
5
|
+
# conftest test path/to/k8s/base/hr.yaml \
|
|
6
|
+
# -p npm/rules/abie/policy/http_route_base \
|
|
7
7
|
# --namespace abie.http_route_base
|
|
8
8
|
#
|
|
9
|
-
# Cross-file gating (саме шлях `…/base
|
|
10
|
-
#
|
|
11
|
-
# `spec.hostnames`.
|
|
12
|
-
# одиничного YAML.
|
|
9
|
+
# Cross-file gating (саме шлях `…/k8s/.../base/...` визначає, чи застосовувати
|
|
10
|
+
# правило) задає glob у `policy/http_route_base/target.json`. Тут — лише
|
|
11
|
+
# валідація вмісту `spec.hostnames`. Rule-level applies-гейт — `js/applies/check.mjs`.
|
|
13
12
|
#
|
|
14
13
|
# Структура каталогу збігається зі шляхом пакету (regal: directory-package-mismatch).
|
|
15
14
|
# Конвенція проєкту — `import rego.v1` + multi-value `deny contains msg if { … }`
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
*/
|
|
9
9
|
import { dirname, relative } from 'node:path'
|
|
10
10
|
|
|
11
|
-
import { pathHasK8sSegment } from '../../k8s/
|
|
11
|
+
import { pathHasK8sSegment } from '../../k8s/js/manifests/check.mjs'
|
|
12
12
|
import { walkDir } from '../../../scripts/utils/walkDir.mjs'
|
|
13
13
|
import { isDeploymentDoc, readAndParseYamlDocs } from './yaml.mjs'
|
|
14
14
|
|
package/rules/adr/adr.mdc
CHANGED
|
@@ -95,7 +95,7 @@ docs/adr/
|
|
|
95
95
|
└── hooks.json # Cursor Agent stop-hooks для тих самих скриптів
|
|
96
96
|
```
|
|
97
97
|
|
|
98
|
-
`.gitignore` у корені проєкту повинен містити базові рядки (`node_modules/`, `dist/`, `*.secret`) і патерни для ADR Stop-hook (**`.claude/hooks/*.log`**, `.claude/hooks/.normalize-state`, `.claude/hooks/.normalize.lock`). Канонічний фрагмент (дописується `npx @nitra/cursor`, коли правило `adr` увімкнене): [.gitignore.snippet](./
|
|
98
|
+
`.gitignore` у корені проєкту повинен містити базові рядки (`node_modules/`, `dist/`, `*.secret`) і патерни для ADR Stop-hook (**`.claude/hooks/*.log`**, `.claude/hooks/.normalize-state`, `.claude/hooks/.normalize.lock`). Канонічний фрагмент (дописується `npx @nitra/cursor`, коли правило `adr` увімкнене): [.gitignore.snippet](./js/hooks/template/.gitignore.snippet).
|
|
99
99
|
|
|
100
100
|
## Stop-hook у `.claude/settings.json`
|
|
101
101
|
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { runStandardRule } from '../../scripts/utils/run-standard-rule.mjs'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Запускає правило: applies → JS-concerns → policy → mdc-refs (через runStandardRule).
|
|
5
|
+
* @param {import('../../scripts/utils/run-standard-rule.mjs').RuleContext} [ctx] контекст прогону (walkCache тощо)
|
|
6
|
+
* @returns {Promise<number>} 0 — OK, 1 — порушення
|
|
7
|
+
*/
|
|
8
|
+
export function run(ctx) {
|
|
9
|
+
return runStandardRule(import.meta.dirname, ctx)
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
if (import.meta.main) {
|
|
13
|
+
// eslint-disable-next-line unicorn/no-process-exit -- standalone entry-point має повертати exit-code для CI/IDE
|
|
14
|
+
process.exit(await run())
|
|
15
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { runStandardRule } from '../../scripts/utils/run-standard-rule.mjs'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Запускає правило: applies → JS-concerns → policy → mdc-refs (через runStandardRule).
|
|
5
|
+
* @param {import('../../scripts/utils/run-standard-rule.mjs').RuleContext} [ctx] контекст прогону (walkCache тощо)
|
|
6
|
+
* @returns {Promise<number>} 0 — OK, 1 — порушення
|
|
7
|
+
*/
|
|
8
|
+
export function run(ctx) {
|
|
9
|
+
return runStandardRule(import.meta.dirname, ctx)
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
if (import.meta.main) {
|
|
13
|
+
// eslint-disable-next-line unicorn/no-process-exit -- standalone entry-point має повертати exit-code для CI/IDE
|
|
14
|
+
process.exit(await run())
|
|
15
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { runStandardRule } from '../../scripts/utils/run-standard-rule.mjs'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Запускає правило: applies → JS-concerns → policy → mdc-refs (через runStandardRule).
|
|
5
|
+
* @param {import('../../scripts/utils/run-standard-rule.mjs').RuleContext} [ctx] контекст прогону (walkCache тощо)
|
|
6
|
+
* @returns {Promise<number>} 0 — OK, 1 — порушення
|
|
7
|
+
*/
|
|
8
|
+
export function run(ctx) {
|
|
9
|
+
return runStandardRule(import.meta.dirname, ctx)
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
if (import.meta.main) {
|
|
13
|
+
// eslint-disable-next-line unicorn/no-process-exit -- standalone entry-point має повертати exit-code для CI/IDE
|
|
14
|
+
process.exit(await run())
|
|
15
|
+
}
|
|
@@ -43,7 +43,7 @@ alwaysApply: true
|
|
|
43
43
|
|
|
44
44
|
**Вимагають bump + нову секцію CHANGELOG** — усі інші зміни в каталозі workspace (код, rego, правила, скіли, конфіги, тести тощо). Виняток `.cursor/` / `.claude/` **не** поширюється на джерело правил у репо `@nitra/cursor` — воно лежить під `npm/`, тож зміни в ньому далі вимагають bump.
|
|
45
45
|
|
|
46
|
-
Перевірка програмна (`changelog/
|
|
46
|
+
Перевірка програмна (`changelog/js/consistency/check.mjs`).
|
|
47
47
|
|
|
48
48
|
## Дві моделі бази порівняння
|
|
49
49
|
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { runStandardRule } from '../../scripts/utils/run-standard-rule.mjs'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Запускає правило: applies → JS-concerns → policy → mdc-refs (через runStandardRule).
|
|
5
|
+
* @param {import('../../scripts/utils/run-standard-rule.mjs').RuleContext} [ctx] контекст прогону (walkCache тощо)
|
|
6
|
+
* @returns {Promise<number>} 0 — OK, 1 — порушення
|
|
7
|
+
*/
|
|
8
|
+
export function run(ctx) {
|
|
9
|
+
return runStandardRule(import.meta.dirname, ctx)
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
if (import.meta.main) {
|
|
13
|
+
// eslint-disable-next-line unicorn/no-process-exit -- standalone entry-point має повертати exit-code для CI/IDE
|
|
14
|
+
process.exit(await run())
|
|
15
|
+
}
|