@nitra/cursor 1.8.171 → 1.8.177
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/.claude-template/npm-CLAUDE.md +9 -4
- package/CHANGELOG.md +47 -0
- package/README.md +14 -0
- package/bin/auto-rules.md +3 -1
- package/mdc/changelog.mdc +64 -0
- package/mdc/k8s.mdc +57 -0
- package/mdc/npm-module.mdc +2 -6
- package/package.json +1 -1
- package/schemas/n-cursor.json +1 -1
- package/scripts/auto-rules.mjs +4 -8
- package/scripts/check-abie.mjs +17 -11
- package/scripts/check-changelog.mjs +402 -0
- package/scripts/check-docker.mjs +12 -5
- package/scripts/check-graphql.mjs +15 -9
- package/scripts/check-hasura.mjs +14 -8
- package/scripts/check-image.mjs +15 -9
- package/scripts/check-js-bun-db.mjs +25 -15
- package/scripts/check-js-mssql.mjs +27 -17
- package/scripts/check-js-run.mjs +26 -16
- package/scripts/check-k8s.mjs +131 -14
- package/scripts/check-nginx-default-tpl.mjs +26 -16
- package/scripts/check-npm-module.mjs +13 -62
- package/scripts/check-vue.mjs +27 -17
- package/scripts/rename-yaml-extensions.mjs +35 -29
- package/scripts/run-docker.mjs +11 -5
- package/scripts/run-k8s.mjs +14 -8
- package/scripts/utils/load-cursor-config.mjs +53 -0
- package/scripts/utils/walkDir.mjs +49 -8
|
@@ -4,20 +4,25 @@
|
|
|
4
4
|
|
|
5
5
|
Path-scoped нагадування для агента: підвантажується автоматично, коли редагуємо файли під `npm/`.
|
|
6
6
|
|
|
7
|
-
## Перед коміт-релевантними змінами в `npm/`
|
|
7
|
+
## Перед PR з коміт-релевантними змінами в `npm/`
|
|
8
8
|
|
|
9
9
|
1. Підвищ `version` у `npm/package.json` (build-bump, не більше одного кроку відносно `HEAD`).
|
|
10
10
|
2. Додай запис у `npm/CHANGELOG.md` форматом Keep a Changelog: `## [версія] - YYYY-MM-DD` + секції `### Added/Changed/Fixed/Removed`.
|
|
11
|
+
3. Переконайся, що `"CHANGELOG.md"` є в масиві `files` у `npm/package.json` (правило `changelog`).
|
|
11
12
|
|
|
12
|
-
|
|
13
|
+
Логіка PR-scoped: bump і запис достатньо зробити **один раз — як суму по всьому PR** (порівняння йде з гілкою `dev`), а не на кожен коміт.
|
|
14
|
+
|
|
15
|
+
Без оновленого CHANGELOG `npx @nitra/cursor check changelog` падає, а `Stop` hook блокує завершення ходу.
|
|
13
16
|
|
|
14
17
|
## Перевірка локально
|
|
15
18
|
|
|
16
19
|
```bash
|
|
20
|
+
npx @nitra/cursor check changelog
|
|
17
21
|
npx @nitra/cursor check npm-module
|
|
18
22
|
```
|
|
19
23
|
|
|
20
24
|
## Джерело правил
|
|
21
25
|
|
|
22
|
-
- `.cursor/rules/n-
|
|
23
|
-
-
|
|
26
|
+
- `.cursor/rules/n-changelog.mdc` — правило про CHANGELOG (PR-scoped, для всіх воркспейсів)
|
|
27
|
+
- `.cursor/rules/n-npm-module.mdc` — правило публікації пакета (типи, hk, npm-publish workflow)
|
|
28
|
+
- `npm/scripts/check-changelog.mjs`, `npm/scripts/check-npm-module.mjs` — алгоритми перевірки
|
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,53 @@
|
|
|
4
4
|
|
|
5
5
|
Формат — [Keep a Changelog](https://keepachangelog.com/uk/1.1.0/), нумерація — [SemVer](https://semver.org/lang/uk/).
|
|
6
6
|
|
|
7
|
+
## [1.8.177] - 2026-05-05
|
|
8
|
+
|
|
9
|
+
### Changed
|
|
10
|
+
|
|
11
|
+
- `changelog` (mdc v2.0): тепер дві моделі бази порівняння на рівні воркспейсу. **npm-published** (`name` + `files` + не `private: true`) — порівняння з опублікованою версією через `npm view <name> version` (git не задіяний; покриває кейс прямих комітів у `main` поза PR-flow). **local-only** (приватні / без `files`) — PR-scoped через `git merge-base <dev> HEAD`, що коректно обробляє: feature-гілку (видно лише унікальні коміти), `main` після merge `dev → main` (diff порожній → правило мовчить), direct-commit на `main` поза PR (ловиться як зміна, що потребує bump). Якщо реєстр недосяжний (офлайн / пакет не публікувався) — fail-safe pass, щоб локальна розробка не блокувалась.
|
|
12
|
+
- `check-changelog.mjs`: повний рефактор. Експорт `check(opts?)` з опційним `getPublishedVersion` для підстановки в тестах (CLI калить без аргументів — використовується дефолтний `npm view`-виклик з 10s таймаутом). Класифікація воркспейсів через `isNpmPublishable(pkg)`; для published — `checkPublishedWorkspace`, для local-only — окрема `runLocalOnlyChecks` із власною skip-логікою (no-git / on dev / no dev ref / no merge-base) і `resolveMergeBase(baseRef)` через `git merge-base`. Спільна `verifyChangelogEntry` для обох режимів.
|
|
13
|
+
- `n-changelog.mdc` / `mdc/changelog.mdc` (v1.1 → 2.0): переписано під дві моделі з прикладами кейсів.
|
|
14
|
+
- Тести `check-changelog.test.mjs`: 16 кейсів (раніше 11) — npm-mode (sync / out-of-sync / no CHANGELOG / no entry / files без `CHANGELOG.md` / offline), local-only skip-логіка, merge-base сценарії (feature-гілка, `main` після merge `dev → main`, direct-commit на `main`), змішаний режим.
|
|
15
|
+
|
|
16
|
+
## [1.8.176] - 2026-05-05
|
|
17
|
+
|
|
18
|
+
### Changed
|
|
19
|
+
|
|
20
|
+
- `changelog` стало єдиним правилом про CHANGELOG для всіх воркспейсів — включно з `npm/`. У `check-npm-module.mjs` прибрано `checkChangelog()` (і константу `CHANGELOG_PATH`); відповідну секцію `## CHANGELOG` видалено з `mdc/npm-module.mdc` (v1.9). Логіка перевірки `npm/CHANGELOG.md` лишилася незмінна за наповненням, але тепер вона PR-scoped (порівняння з `dev`), тож на feature-гілці bump і запис достатньо зробити **один раз — як суму по PR**, без bump-шуму в проміжних комітах.
|
|
21
|
+
- `check-changelog.mjs`: додано перевірку `files`-масиву — якщо `<ws>/package.json` його оголошує, у ньому має бути `"CHANGELOG.md"` (приватні воркспейси без `files` цей пункт пропускають). Прибрано `SKIP_WORKSPACE = 'npm'` — `npm/` тепер у звичайному циклі. Хелпер `readPackageJsonOrNull` об'єднує читання `package.json` (раніше було два окремі читачі — `version` і `files`).
|
|
22
|
+
- `auto-rules.mjs` / `auto-rules.md`: `changelog` переведено на `AUTO_RULE_DEPENDENCIES = ['bun']` (раніше — пряма умова `packageJsonExists`); тепер послідовно з рештою правил.
|
|
23
|
+
- `npm/.claude-template/npm-CLAUDE.md` (і згенерований `npm/CLAUDE.md`): оновлено — посилається на `n-changelog.mdc`, явно згадує `files: ["CHANGELOG.md"]`, наголошує на PR-scoped логіці.
|
|
24
|
+
- Тести `check-changelog.test.mjs`: кейс `npm/ пропускається` замінено на `npm/ перевіряється з files=["CHANGELOG.md"]`; додано окремий кейс fail при `files` без `CHANGELOG.md`.
|
|
25
|
+
|
|
26
|
+
## [1.8.175] - 2026-05-05
|
|
27
|
+
|
|
28
|
+
### Added
|
|
29
|
+
|
|
30
|
+
- `k8s.mdc` / `check-k8s.mjs`: у маршрутах Gateway API (**HTTPRoute**, **GRPCRoute**, **TCPRoute**, **TLSRoute**, **UDPRoute**, група `gateway.networking.k8s.io`) забороняється поле `namespace` у `spec.rules[*].backendRefs[*]` (і однини `backendRef`), якщо його значення збігається з `metadata.namespace` самого маршруту. За замовчуванням Gateway API резолвить backend у тому ж namespace, що й маршрут — дублювання у `backendRef` мертве й заважає Kustomize-overlay, що міняє namespace маршруту. Cross-namespace backendRef (з відмінним `namespace`) правило не торкається. Експортовано `collectGatewayApiRouteBackendRefsWithRedundantNamespace(spec, routeNs)`; перевіряється усередині існуючого `failIfGatewayRouteUsesNonHeadlessService` (той самий обхід дерева, що й для headless-перевірки). Додано приклад «погано/добре» у `k8s.mdc` і відповідні юніт-тести.
|
|
31
|
+
|
|
32
|
+
## [1.8.174] - 2026-05-05
|
|
33
|
+
|
|
34
|
+
### Added
|
|
35
|
+
|
|
36
|
+
- Нове правило `changelog` (`mdc/changelog.mdc` + `scripts/check-changelog.mjs`): для «звичайних» Bun-монорепо проєктів вимагає, щоб у кожному workspace, який змінився відносно базової гілки `dev`, у поточному PR було підвищено `version` у `<ws>/package.json` і додано запис `## [version] - YYYY-MM-DD` у `<ws>/CHANGELOG.md` (Keep a Changelog 1.1.0). Перевірка PR-scoped: на самій гілці `dev` пропускається; на feature-гілці bump і запис достатньо зробити **один раз — як суму по всьому PR**, без бамп-шуму в проміжних комітах. Воркспейс `npm/` пропускається — його CHANGELOG покриває окреме правило `npm-module`. У `auto-rules.md` / `auto-rules.mjs` `changelog` додано до автодетекту з умовою «у корені є `package.json`» і до `AUTO_RULE_ORDER` між `capacitor` і `docker`.
|
|
37
|
+
|
|
38
|
+
### Added
|
|
39
|
+
|
|
40
|
+
- `.n-cursor.json` поле `ignore` (`schemas/n-cursor.json`): тепер не лише сигнал для AI, а й керує обходом усіх `check-*.mjs` / `run-*.mjs` — перелічені каталоги повністю виключаються з `walkDir`, як `node_modules` чи `.git`. Дозволяє безпечно тримати vendored Helm-чарти, генеровані маніфести, legacy-дерева у репо без false-positive’ів від check-скриптів. Розширено опис у схемі (стандартні виключення додавати не треба) і README отримав секцію «Виключення цілих дерев».
|
|
41
|
+
- `scripts/utils/load-cursor-config.mjs`: нова утиліта `loadCursorIgnorePaths(root)` — читає поле `ignore` з `.n-cursor.json` і нормалізує до абсолютних posix-шляхів без trailing-slash; пропускає не-рядки та порожні елементи; повертає `[]`, якщо файлу/поля нема або JSON невалідний.
|
|
42
|
+
- `scripts/utils/walkDir.mjs`: третій аргумент `ignorePaths` (за замовчуванням `[]`) — каталоги, які пропускаються разом з усім вмістом. Збіг — за повним шляхом (точний або з префіксом `/`), а не за basename, тож `postgres-master-test/` не пропускається коли в ignore лише `postgres-master/`. Стандартні пропуски (`node_modules`, `.git`, `dist`, `coverage`, `.turbo`, `.next`) працюють як раніше.
|
|
43
|
+
|
|
44
|
+
### Changed
|
|
45
|
+
|
|
46
|
+
- Усі скрипти, що обходять FS через `walkDir`, тепер на початку `check()` зчитують `loadCursorIgnorePaths(root)` і передають третім аргументом: `check-abie`, `check-docker`, `check-graphql`, `check-hasura`, `check-image`, `check-js-bun-db`, `check-js-mssql`, `check-js-run`, `check-k8s`, `check-nginx-default-tpl`, `check-npm-module`, `check-vue`, плюс `run-docker`, `run-k8s` і `rename-yaml-extensions`. Wrapper-функції (`findDockerfilePaths`, `findK8sYamlFiles`, `findLintDockerfilePaths`, `findK8sRoots`, `findDefaultConfTemplatePaths`, `migrateDefaultTplConfFiles`) отримали опційний параметр `ignorePaths` для прозорого пробросу.
|
|
47
|
+
|
|
48
|
+
## [1.8.172] - 2026-05-04
|
|
49
|
+
|
|
50
|
+
### Changed
|
|
51
|
+
|
|
52
|
+
- `auto-rules.md` / `auto-rules.mjs`: правило `php` тепер автоувімкається за наявністю `composer.json` у корені, а не за будь-яким `*.php` файлом у дереві. Прибрано константу `PHP_RE`, факт `hasPhpSource` і його збір у `updateFileFacts`/`collectAutoRuleFacts`; натомість у `detectAutoRulesAndSkills` додано прапорець `composerJsonExists` (за аналогією з `packageJsonExists` / `npmDirExists`).
|
|
53
|
+
|
|
7
54
|
## [1.8.171] - 2026-05-04
|
|
8
55
|
|
|
9
56
|
### Removed
|
package/README.md
CHANGED
|
@@ -30,6 +30,20 @@
|
|
|
30
30
|
|
|
31
31
|
Щоб використовувати конкретну версію правил, оновіть залежність `@nitra/cursor` у проєкті (`bun add -d @nitra/cursor@<версія>` тощо). Поле `version` у `.n-cursor.json`, якщо воно лишилось у старих конфігах, **ігнорується**.
|
|
32
32
|
|
|
33
|
+
### Виключення цілих дерев — поле `ignore`
|
|
34
|
+
|
|
35
|
+
Поле `ignore` у `.n-cursor.json` — список директорій (posix-шляхи відносно кореня репозиторію), які CLI повністю пропускає під час обходу: жоден `check-*.mjs` не сканує і не валідує файли всередині них, а агент не редагує/не створює/не видаляє там файли. Стандартні виключення (`node_modules`, `.git`, `dist`, `coverage`, `.turbo`, `.next`) працюють завжди — додавати їх у `ignore` не потрібно.
|
|
36
|
+
|
|
37
|
+
Типові кандидати: vendored Helm-чарти, генеровані маніфести, legacy-дерева, які не підтягуються під поточні правила:
|
|
38
|
+
|
|
39
|
+
```json
|
|
40
|
+
{
|
|
41
|
+
"$schema": "https://unpkg.com/@nitra/cursor/schemas/n-cursor.json",
|
|
42
|
+
"rules": ["k8s"],
|
|
43
|
+
"ignore": ["dremio/dev/dremio_v2", "postgres-master"]
|
|
44
|
+
}
|
|
45
|
+
```
|
|
46
|
+
|
|
33
47
|
### Правило `k8s` і Kustomize
|
|
34
48
|
|
|
35
49
|
У цільовому репозиторії з маніфестами під **`**/k8s`** дотримуйтесь **`mdc/k8s.mdc`** з пакету (після синку — `.cursor/rules/n-k8s.mdc`або копія з`node_modules/@nitra/cursor/mdc/k8s.mdc`).
|
package/bin/auto-rules.md
CHANGED
|
@@ -12,6 +12,8 @@ bun - якщо в корені проекту є package.json
|
|
|
12
12
|
|
|
13
13
|
capacitor - якщо в проекті є хоч один файл capacitor.config.json
|
|
14
14
|
|
|
15
|
+
changelog - [bun]
|
|
16
|
+
|
|
15
17
|
docker - якщо в проекті є хоч один Dockerfile
|
|
16
18
|
|
|
17
19
|
ga - якщо присутня директорія .github/workflows
|
|
@@ -36,7 +38,7 @@ nginx-default-tpl - якщо присутній хоч один файл з пе
|
|
|
36
38
|
|
|
37
39
|
npm-module - якщо в корені присутня директорія npm
|
|
38
40
|
|
|
39
|
-
php - якщо
|
|
41
|
+
php - якщо в корені є composer.json
|
|
40
42
|
|
|
41
43
|
style-lint - якщо присутній хоч один vue або css файл
|
|
42
44
|
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: CHANGELOG.md в кожному workspace, з двома моделями бази порівняння
|
|
3
|
+
alwaysApply: true
|
|
4
|
+
version: '2.0'
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
Bun monorepo: у кожному workspace із кореневого `package.json.workspaces` (плюс кореневий пакет, плюс `npm/`) має бути власний **`CHANGELOG.md`**. Спільного на репозиторій змісту змін **не існує** — кожен пакет веде свій. Правило `npm-module` відповідає лише за публікацію типів і workflow, а CHANGELOG — за цим правилом.
|
|
8
|
+
|
|
9
|
+
## Дві моделі бази порівняння
|
|
10
|
+
|
|
11
|
+
Правило за **`<ws>/package.json`** автоматично визначає режим перевірки:
|
|
12
|
+
|
|
13
|
+
### npm-published воркспейс
|
|
14
|
+
|
|
15
|
+
Якщо в `<ws>/package.json` є непорожнє `name`, **не** `private: true` і оголошено масив `files` — workspace публікується в npm. База — **опублікована версія в реєстрі** (`npm view <name> version`):
|
|
16
|
+
|
|
17
|
+
1. Якщо локальна `version` дорівнює опублікованій — ще нічого не зрелізнуто, перевірка мовчить.
|
|
18
|
+
2. Якщо локальна `version` відрізняється від опублікованої — потрібен запис у `<ws>/CHANGELOG.md` для локальної версії (формат `## [версія] - YYYY-MM-DD`) і `"CHANGELOG.md"` у `files`.
|
|
19
|
+
3. Якщо реєстр недосяжний (офлайн / пакет ще не публікувався) — fail-safe pass із поясненням, щоб локальна розробка не блокувалася.
|
|
20
|
+
|
|
21
|
+
Git у цьому режимі не використовується — порівнюється поточний стан робочої копії з тим, що насправді в npm. Це покриває кейс «прямі коміти в `main` поза PR-flow» автоматично, бо неопубліковані зміни одразу видно.
|
|
22
|
+
|
|
23
|
+
### local-only воркспейс
|
|
24
|
+
|
|
25
|
+
Якщо workspace приватний (`private: true`) або без `files` (apps, services, internal-only пакети) — база = **гілка `dev`**, точніше `git merge-base <dev> HEAD`:
|
|
26
|
+
|
|
27
|
+
1. На самій гілці `dev` правило не активне.
|
|
28
|
+
2. На feature-гілці merge-base = точка розгалуження від `dev` → видно лише унікальні коміти цієї гілки. Bump + запис у `CHANGELOG.md` потрібні **раз на весь PR — як сума по гілці**, без bump-шуму в проміжних комітах.
|
|
29
|
+
3. На `main` після merge `dev → main` merge-base = поточний `dev` → diff порожній → правило мовчить.
|
|
30
|
+
4. Direct-commit на `main` поза PR-flow ловиться як зміна, що потребує bump + запис у `CHANGELOG.md`.
|
|
31
|
+
|
|
32
|
+
Якщо не git-репо, або `dev`/`origin/dev` не існує — local-only перевірка пропускається.
|
|
33
|
+
|
|
34
|
+
## Формат CHANGELOG.md
|
|
35
|
+
|
|
36
|
+
[Keep a Changelog 1.1.0](https://keepachangelog.com/uk/1.1.0/), мова — українська, новіші версії зверху.
|
|
37
|
+
|
|
38
|
+
```md title="<ws>/CHANGELOG.md"
|
|
39
|
+
# Changelog
|
|
40
|
+
|
|
41
|
+
Усі помітні зміни цього пакета документуються тут.
|
|
42
|
+
|
|
43
|
+
Формат — [Keep a Changelog](https://keepachangelog.com/uk/1.1.0/), нумерація — [SemVer](https://semver.org/lang/uk/).
|
|
44
|
+
|
|
45
|
+
## [1.2.3] - 2026-05-05
|
|
46
|
+
|
|
47
|
+
### Added
|
|
48
|
+
|
|
49
|
+
- ...
|
|
50
|
+
|
|
51
|
+
### Changed
|
|
52
|
+
|
|
53
|
+
- ...
|
|
54
|
+
|
|
55
|
+
### Fixed
|
|
56
|
+
|
|
57
|
+
- ...
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Секції — підмножина `### Added`, `### Changed`, `### Fixed`, `### Removed` (одна або кілька).
|
|
61
|
+
|
|
62
|
+
## Перевірка
|
|
63
|
+
|
|
64
|
+
`npx @nitra/cursor check changelog`
|
package/mdc/k8s.mdc
CHANGED
|
@@ -214,6 +214,41 @@ spec:
|
|
|
214
214
|
|
|
215
215
|
**Точні умови та повідомлення `fail`** — верхній JSDoc **`npm/scripts/check-k8s.mjs`**.
|
|
216
216
|
|
|
217
|
+
### Gateway API: не дублюй namespace у `backendRef`
|
|
218
|
+
|
|
219
|
+
У маршрутах Gateway API (**HTTPRoute**, **GRPCRoute**, **TCPRoute**, **TLSRoute**, **UDPRoute**) у `spec.rules[*].backendRefs[*]` **не** додавай поле **`namespace`**, якщо його значення збігається з **`metadata.namespace`** самого маршруту. За замовчуванням Gateway API резолвить backend у тому ж namespace, що й маршрут, тож такий рядок — мертвий: він плутає під час перенесень між середовищами і ламається мовчки, якщо overlay змінює namespace маршруту через Kustomize, а в backendRef залишився старий рядок. Прибери поле — поведінка не зміниться. **`check k8s`** падає на такому збігу.
|
|
220
|
+
|
|
221
|
+
```yaml
|
|
222
|
+
# ❌ погано — namespace дублює metadata.namespace маршруту
|
|
223
|
+
apiVersion: gateway.networking.k8s.io/v1
|
|
224
|
+
kind: HTTPRoute
|
|
225
|
+
metadata:
|
|
226
|
+
name: admin-site
|
|
227
|
+
namespace: dev-b2b
|
|
228
|
+
spec:
|
|
229
|
+
rules:
|
|
230
|
+
- backendRefs:
|
|
231
|
+
- name: auth-hl
|
|
232
|
+
namespace: dev-b2b # ← прибери
|
|
233
|
+
port: 8080
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
```yaml
|
|
237
|
+
# ✅ добре — namespace лише в metadata
|
|
238
|
+
apiVersion: gateway.networking.k8s.io/v1
|
|
239
|
+
kind: HTTPRoute
|
|
240
|
+
metadata:
|
|
241
|
+
name: admin-site
|
|
242
|
+
namespace: dev-b2b
|
|
243
|
+
spec:
|
|
244
|
+
rules:
|
|
245
|
+
- backendRefs:
|
|
246
|
+
- name: auth-hl
|
|
247
|
+
port: 8080
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
Якщо backend **дійсно** живе в іншому namespace — поле **`namespace`** у `backendRef` обов'язкове (і потрібен `ReferenceGrant` у тому namespace); правило цього випадку не торкається.
|
|
251
|
+
|
|
217
252
|
## ConfigMap: ім'я збігається з Deployment
|
|
218
253
|
|
|
219
254
|
Якщо в `k8s/base/` є **`configmap.yaml`** і **Deployment**, і цей Deployment посилається рівно на **один** ConfigMap — `metadata.name` ConfigMap має збігатися з `metadata.name` Deployment. Точні умови перевірки — **`check-k8s.mjs`**.
|
|
@@ -474,6 +509,28 @@ patches:
|
|
|
474
509
|
preem: "false"
|
|
475
510
|
```
|
|
476
511
|
|
|
512
|
+
### `patches[].target`: лише `kind` і `name`
|
|
513
|
+
|
|
514
|
+
У `patches[].target` залишай **тільки** **`kind`** і **`name`** — поля **`group`** і **`version`** прибирай. Kustomize резолвить ціль за GVK+name; `group`/`version` — звужувальні фільтри, потрібні лише за реальної колізії `kind+name` між різними API-групами або версіями. У межах одного namespace apiserver зберігає об'єкт у єдиному storage-GVK, тож для звичайних маніфестів така колізія неможлива, і `group`/`version` у `target` — мертвий шум, який ламається мовчки під час змін API (наприклад, перехід `v1beta1` → `v1`).
|
|
515
|
+
|
|
516
|
+
```yaml
|
|
517
|
+
# ❌ зайві group / version
|
|
518
|
+
patches:
|
|
519
|
+
- target:
|
|
520
|
+
group: gateway.networking.k8s.io
|
|
521
|
+
version: v1beta1
|
|
522
|
+
kind: Gateway
|
|
523
|
+
name: gw
|
|
524
|
+
|
|
525
|
+
# ✅
|
|
526
|
+
patches:
|
|
527
|
+
- target:
|
|
528
|
+
kind: Gateway
|
|
529
|
+
name: gw
|
|
530
|
+
```
|
|
531
|
+
|
|
532
|
+
**Виняток:** залишай `group` / `version`, лише якщо в дереві overlay реально співіснують ресурси з однаковими `kind`+`name`, але різними API-групами/версіями (наприклад, дві CRD з одним `kind`). У такому разі вкажи мінімальний набір полів, потрібний для дисамбігуації.
|
|
533
|
+
|
|
477
534
|
## Перевірка
|
|
478
535
|
|
|
479
536
|
**`npx @nitra/cursor check k8s`** — програмні критерії в **JSDoc на початку** **`npm/scripts/check-k8s.mjs`**. Якщо під **`k8s`** немає **`*.yaml`** — крок пропущено. Канон **`$schema`** для редактора — розділ **«Визначення схеми YAML`** нижче.
|
package/mdc/npm-module.mdc
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
description: Оформлення репозиторію для npm модуля
|
|
3
3
|
alwaysApply: true
|
|
4
|
-
version: '1.
|
|
4
|
+
version: '1.9'
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
Bun monorepo: workspace **`npm/`**, кореневий **`package.json`**, **`.github/workflows/`**; опційно **`demo/`**.
|
|
@@ -51,11 +51,7 @@ bunx -p typescript tsc src/**/*.js --declaration --allowJs --emitDeclarationOnly
|
|
|
51
51
|
|
|
52
52
|
## CHANGELOG
|
|
53
53
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
Формат — [Keep a Changelog](https://keepachangelog.com/uk/1.1.0/) (новіші версії зверху, мова — українська). Кожен запис починається з рядка `## [версія] - YYYY-MM-DD` і має одну або кілька секцій: `### Added`, `### Changed`, `### Fixed`, `### Removed`.
|
|
57
|
-
|
|
58
|
-
Файл **`CHANGELOG.md`** має бути в масиві **`files`** у **`npm/package.json`**, щоб публікувався разом із пакетом.
|
|
54
|
+
Окреме правило **`changelog`** ([changelog.mdc](changelog.mdc)) вимагає `npm/CHANGELOG.md` із записом для поточної версії (Keep a Changelog) і присутність `"CHANGELOG.md"` у масиві `files` у `npm/package.json`. Логіка — PR-scoped (сума по гілці vs `dev`).
|
|
59
55
|
|
|
60
56
|
## npm publish
|
|
61
57
|
|
package/package.json
CHANGED
package/schemas/n-cursor.json
CHANGED
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
},
|
|
46
46
|
"ignore": {
|
|
47
47
|
"type": "array",
|
|
48
|
-
"description": "Директорії,
|
|
48
|
+
"description": "Директорії, що повністю виключаються з обходу check-скриптів CLI (npx @nitra/cursor check ...) і AI-модифікацій (AI не редагує, не видаляє, не створює файли). Шляхи відносно кореня репозиторію (posix). Приклади: vendored Helm-чарти, генеровані маніфести, legacy-дерева. Стандартні виключення (node_modules, .git, dist, coverage, .turbo, .next) застосовуються завжди — додавати їх не треба.",
|
|
49
49
|
"items": {
|
|
50
50
|
"type": "string",
|
|
51
51
|
"minLength": 1
|
package/scripts/auto-rules.mjs
CHANGED
|
@@ -26,6 +26,7 @@ export const AUTO_RULE_ORDER = Object.freeze([
|
|
|
26
26
|
'abie',
|
|
27
27
|
'bun',
|
|
28
28
|
'capacitor',
|
|
29
|
+
'changelog',
|
|
29
30
|
'docker',
|
|
30
31
|
'ga',
|
|
31
32
|
'graphql',
|
|
@@ -54,6 +55,7 @@ export const AUTO_SKILL_ORDER = Object.freeze(['abie-kustomize', 'fix', 'lint'])
|
|
|
54
55
|
*/
|
|
55
56
|
export const AUTO_RULE_DEPENDENCIES = Object.freeze(
|
|
56
57
|
/** @type {Record<string, readonly string[]>} */ ({
|
|
58
|
+
changelog: Object.freeze(['bun']),
|
|
57
59
|
image: Object.freeze(['vue'])
|
|
58
60
|
})
|
|
59
61
|
)
|
|
@@ -63,7 +65,6 @@ const HASURA_CONFIG_MARKER = 'metadata_directory: metadata'
|
|
|
63
65
|
const JS_LIKE_RE = /\.(?:mjs|cjs|js|jsx|ts|tsx)$/iu
|
|
64
66
|
const STYLE_RE = /\.(?:css|vue)$/iu
|
|
65
67
|
const VUE_RE = /\.vue$/iu
|
|
66
|
-
const PHP_RE = /\.php$/iu
|
|
67
68
|
const NGINX_DEFAULT_FILES = new Set(['default.conf.template', 'default.conf', 'nginx.conf'])
|
|
68
69
|
const IGNORED_DIR_NAMES = new Set(['node_modules', '.git', '.next', '.turbo'])
|
|
69
70
|
const DEFAULT_DISABLED_LIST = Object.freeze([])
|
|
@@ -245,7 +246,6 @@ function updateDirFacts(dirName, facts) {
|
|
|
245
246
|
* hasDockerfile: boolean,
|
|
246
247
|
* hasJsLikeSource: boolean,
|
|
247
248
|
* hasNginxDefaultTplFile: boolean,
|
|
248
|
-
* hasPhpSource: boolean,
|
|
249
249
|
* hasVueOrCssSource: boolean,
|
|
250
250
|
* hasVueSource: boolean
|
|
251
251
|
* }} facts агреговані факти
|
|
@@ -267,9 +267,6 @@ function updateFileFacts(fileName, relPath, facts) {
|
|
|
267
267
|
if (VUE_RE.test(relPath)) {
|
|
268
268
|
facts.hasVueSource = true
|
|
269
269
|
}
|
|
270
|
-
if (PHP_RE.test(relPath)) {
|
|
271
|
-
facts.hasPhpSource = true
|
|
272
|
-
}
|
|
273
270
|
if (STYLE_RE.test(relPath)) {
|
|
274
271
|
facts.hasVueOrCssSource = true
|
|
275
272
|
}
|
|
@@ -452,7 +449,6 @@ export function isMonorepoPackage(packageJson) {
|
|
|
452
449
|
* hasK8sDir: boolean,
|
|
453
450
|
* hasNginxDefaultTplFile: boolean,
|
|
454
451
|
* hasTempoDir: boolean,
|
|
455
|
-
* hasPhpSource: boolean,
|
|
456
452
|
* hasVueSource: boolean,
|
|
457
453
|
* hasVueOrCssSource: boolean
|
|
458
454
|
* }>} агреговані факти
|
|
@@ -469,7 +465,6 @@ export async function collectAutoRuleFacts(root) {
|
|
|
469
465
|
hasK8sDir: false,
|
|
470
466
|
hasNginxDefaultTplFile: false,
|
|
471
467
|
hasTempoDir: false,
|
|
472
|
-
hasPhpSource: false,
|
|
473
468
|
hasVueSource: false,
|
|
474
469
|
hasVueOrCssSource: false
|
|
475
470
|
}
|
|
@@ -556,6 +551,7 @@ export async function detectAutoRulesAndSkills({
|
|
|
556
551
|
|
|
557
552
|
const packageJsonExists = existsSync(join(root, 'package.json'))
|
|
558
553
|
const npmDirExists = existsSync(join(root, 'npm'))
|
|
554
|
+
const composerJsonExists = existsSync(join(root, 'composer.json'))
|
|
559
555
|
const repositoryUrl = getRepositoryUrl(
|
|
560
556
|
packageJsonParsed && typeof packageJsonParsed === 'object' && !Array.isArray(packageJsonParsed)
|
|
561
557
|
? /** @type {Record<string, unknown>} */ (packageJsonParsed).repository
|
|
@@ -612,7 +608,7 @@ export async function detectAutoRulesAndSkills({
|
|
|
612
608
|
{ enabled: facts.hasK8sDir, id: 'k8s' },
|
|
613
609
|
{ enabled: facts.hasNginxDefaultTplFile, id: 'nginx-default-tpl' },
|
|
614
610
|
{ enabled: npmDirExists, id: 'npm-module' },
|
|
615
|
-
{ enabled:
|
|
611
|
+
{ enabled: composerJsonExists, id: 'php' },
|
|
616
612
|
{ enabled: facts.hasVueOrCssSource, id: 'style-lint' }
|
|
617
613
|
]
|
|
618
614
|
for (const item of autoRuleChecks) {
|
package/scripts/check-abie.mjs
CHANGED
|
@@ -47,6 +47,7 @@ import { parseAllDocuments } from 'yaml'
|
|
|
47
47
|
import { pathHasK8sSegment, ruKustomizationHasHealthCheckDeletePatch } from './check-k8s.mjs'
|
|
48
48
|
import { createCheckReporter } from './utils/check-reporter.mjs'
|
|
49
49
|
import { flattenWorkflowSteps, getStepUses, parseWorkflowYaml } from './utils/gha-workflow.mjs'
|
|
50
|
+
import { loadCursorIgnorePaths } from './utils/load-cursor-config.mjs'
|
|
50
51
|
import { walkDir } from './utils/walkDir.mjs'
|
|
51
52
|
|
|
52
53
|
const CONFIG_FILE = '.n-cursor.json'
|
|
@@ -385,18 +386,22 @@ export function ignoreBranchesIncludesRequired(ignoreBranches, required) {
|
|
|
385
386
|
* @param {string} root корінь репозиторію
|
|
386
387
|
* @returns {Promise<string[]>} відсортовані шляхи
|
|
387
388
|
*/
|
|
388
|
-
async function findK8sYamlFiles(root) {
|
|
389
|
+
async function findK8sYamlFiles(root, ignorePaths = []) {
|
|
389
390
|
/** @type {string[]} */
|
|
390
391
|
const out = []
|
|
391
|
-
await walkDir(
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
392
|
+
await walkDir(
|
|
393
|
+
root,
|
|
394
|
+
p => {
|
|
395
|
+
if (!pathHasK8sSegment(p)) {
|
|
396
|
+
return
|
|
397
|
+
}
|
|
398
|
+
if (!YAML_EXTENSION_RE.test(p)) {
|
|
399
|
+
return
|
|
400
|
+
}
|
|
401
|
+
out.push(p)
|
|
402
|
+
},
|
|
403
|
+
ignorePaths
|
|
404
|
+
)
|
|
400
405
|
return [...out].toSorted((a, b) => a.localeCompare(b))
|
|
401
406
|
}
|
|
402
407
|
|
|
@@ -2088,7 +2093,8 @@ export async function check() {
|
|
|
2088
2093
|
await ensureNoFirebaseHostingArtifacts(root, pass, fail)
|
|
2089
2094
|
await checkCleanMergedBranch(root, pass, fail)
|
|
2090
2095
|
|
|
2091
|
-
const
|
|
2096
|
+
const ignorePaths = await loadCursorIgnorePaths(root)
|
|
2097
|
+
const yamlFiles = await findK8sYamlFiles(root, ignorePaths)
|
|
2092
2098
|
const deploymentDirs = await collectDeploymentDirs(root, yamlFiles, fail)
|
|
2093
2099
|
|
|
2094
2100
|
if (deploymentDirs.size > 0) {
|