@nitra/cursor 1.13.82 → 1.13.84
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/commands/n-check.md +2 -2
- package/CHANGELOG.md +59 -26
- package/README.md +11 -11
- package/bin/n-cursor.js +38 -67
- package/package.json +1 -1
- package/rules/abie/abie.mdc +9 -9
- package/rules/abie/fix.mjs +19 -0
- package/rules/abie/policy/base_deployment_preem/base_deployment_preem.rego +2 -2
- package/rules/abie/policy/health_check_policy/health_check_policy.rego +2 -2
- package/rules/abie/policy/http_route_base/http_route_base.rego +1 -1
- package/rules/abie/utils/k8s-tree.mjs +1 -1
- package/rules/adr/adr.mdc +1 -1
- package/rules/adr/fix.mjs +19 -0
- package/rules/adr/{fix → js}/hooks/check.mjs +1 -1
- package/rules/bun/bun.mdc +1 -1
- package/rules/bun/fix.mjs +19 -0
- package/rules/bun/{fix → js}/layout/check.mjs +1 -1
- package/rules/capacitor/fix.mjs +19 -0
- package/rules/capacitor/policy/package_json/package_json.rego +3 -3
- package/rules/changelog/changelog.mdc +2 -2
- package/rules/changelog/fix.mjs +19 -0
- package/rules/ci4/ci4.mdc +1 -1
- package/rules/ci4/fix.mjs +19 -0
- package/rules/docker/docker.mdc +7 -7
- package/rules/docker/fix.mjs +19 -0
- package/rules/docker/lint/lint.mjs +2 -2
- package/rules/docker/policy/package_json/package_json.rego +1 -1
- package/rules/efes/efes.mdc +1 -1
- package/rules/efes/fix.mjs +19 -0
- package/rules/feedback/feedback.mdc +2 -2
- package/rules/feedback/fix.mjs +19 -0
- package/rules/ga/fix.mjs +19 -0
- package/rules/ga/lint/lint.mjs +6 -6
- package/rules/ga/policy/workflow_common/workflow_common.rego +1 -1
- package/rules/graphql/fix.mjs +19 -0
- package/rules/graphql/{fix → js}/tooling/graphql-gql-scan.mjs +1 -1
- package/rules/graphql/policy/vscode_extensions/vscode_extensions.rego +2 -2
- package/rules/hasura/fix.mjs +19 -0
- package/rules/hasura/policy/svc_hl/svc_hl.rego +1 -1
- package/rules/image-avif/fix.mjs +19 -0
- package/rules/image-avif/image-avif.mdc +1 -1
- package/rules/image-avif/{fix → js}/avif_generation/check.mjs +1 -1
- package/rules/image-compress/fix.mjs +19 -0
- package/rules/image-compress/{fix → js}/package_setup/check.mjs +1 -1
- package/rules/js-bun-db/fix.mjs +19 -0
- package/rules/js-bun-redis/fix.mjs +19 -0
- package/rules/js-bun-redis/policy/package_json/package_json.rego +1 -1
- package/rules/js-lint/fix.mjs +19 -0
- package/rules/js-lint/{fix → js}/tooling/check.mjs +5 -5
- package/rules/js-lint/{fix → js}/tooling/rebuild-oxlint-canonical.mjs +1 -1
- package/rules/js-lint/js-lint.mdc +3 -3
- package/rules/js-mssql/fix.mjs +19 -0
- package/rules/js-mssql/policy/package_json/package_json.rego +2 -2
- package/rules/js-run/fix.mjs +19 -0
- package/rules/js-run/{fix → js}/runtime/check.mjs +3 -3
- package/rules/k8s/fix.mjs +19 -0
- package/rules/k8s/{fix → js}/manifests/check.mjs +1 -1
- package/rules/k8s/k8s.mdc +13 -13
- package/rules/k8s/lint/lint.mjs +2 -2
- package/rules/k8s/policy/base_kustomization/base_kustomization.rego +3 -3
- package/rules/k8s/policy/base_manifest/base_manifest.rego +2 -2
- package/rules/k8s/policy/gateway/gateway.rego +2 -2
- package/rules/k8s/policy/hasura_configmap/hasura_configmap.rego +3 -3
- package/rules/k8s/policy/hasura_httproute/hasura_httproute.rego +1 -1
- package/rules/k8s/policy/hpa_pdb/hpa_pdb.rego +1 -1
- package/rules/k8s/policy/kustomization/kustomization.rego +2 -2
- package/rules/k8s/policy/manifest/manifest.rego +4 -4
- package/rules/k8s/policy/svc_hl_yaml/svc_hl_yaml.rego +2 -2
- package/rules/k8s/policy/svc_yaml/svc_yaml.rego +2 -2
- package/rules/nginx-default-tpl/fix.mjs +19 -0
- package/rules/nginx-default-tpl/{fix → js}/template/check.mjs +1 -1
- package/rules/nginx-default-tpl/policy/vscode_extensions/vscode_extensions.rego +2 -2
- package/rules/nginx-default-tpl/policy/vscode_settings/vscode_settings.rego +1 -1
- package/rules/npm-module/fix.mjs +19 -0
- package/rules/npm-module/{fix → js}/package_structure/check.mjs +3 -3
- package/rules/php/fix.mjs +19 -0
- package/rules/php/{fix → js}/tooling/check.mjs +2 -2
- package/rules/rego/fix.mjs +19 -0
- package/rules/security/fix.mjs +19 -0
- package/rules/security/security.mdc +3 -3
- package/rules/style-lint/fix.mjs +19 -0
- package/rules/style-lint/{fix → js}/tooling/check.mjs +2 -2
- package/rules/tauri/fix.mjs +19 -0
- package/rules/tauri/{fix → js}/tooling/check.mjs +1 -1
- package/rules/tauri/policy/vscode_extensions/vscode_extensions.rego +2 -2
- package/rules/test/fix.mjs +19 -0
- package/rules/test/test.mdc +2 -2
- package/rules/text/fix.mjs +19 -0
- package/rules/text/{fix → js}/formatting/check.mjs +2 -2
- package/rules/text/text.mdc +1 -1
- package/rules/vue/fix.mjs +19 -0
- package/rules/vue/{fix → js}/packages/check.mjs +1 -1
- package/rules/vue/policy/package_json/package_json.rego +1 -1
- package/rules/vue/vue.mdc +1 -1
- package/schemas/n-cursor.json +1 -1
- package/scripts/auto-rules.mjs +3 -3
- package/scripts/build-agents-commands.mjs +1 -1
- package/scripts/claude-stop-hook.mjs +1 -1
- package/scripts/sync-claude-config.mjs +2 -2
- package/scripts/utils/ast-scan-utils.mjs +3 -3
- package/scripts/utils/discover-check-rules-from-cursor.mjs +1 -1
- package/scripts/utils/discover-checkable-rules.mjs +30 -18
- package/scripts/utils/list-rule-ids.mjs +23 -0
- package/scripts/utils/read-n-cursor-config-lite.mjs +59 -0
- package/scripts/utils/run-rule-cli.mjs +37 -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/workspaces.mjs +1 -1
- package/skills/fix/SKILL.md +5 -5
- package/skills/lint/SKILL.md +1 -1
- /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/template/.gitignore.snippet +0 -0
- /package/rules/capacitor/{fix → js}/platforms/check.mjs +0 -0
- /package/rules/changelog/{fix → js}/consistency/check.mjs +0 -0
- /package/rules/changelog/{fix → js}/consistency/package-manifest.mjs +0 -0
- /package/rules/docker/{fix → js}/lint/check.mjs +0 -0
- /package/rules/docker/{fix → js}/lint/docker-hadolint.mjs +0 -0
- /package/rules/docker/{fix → js}/lint/docker-mirror.mjs +0 -0
- /package/rules/ga/{fix → js}/workflows/check.mjs +0 -0
- /package/rules/graphql/{fix → js}/tooling/check.mjs +0 -0
- /package/rules/hasura/{fix → js}/internal_urls/check.mjs +0 -0
- /package/rules/js-bun-db/{fix → js}/safety/bun-sql-scan.mjs +0 -0
- /package/rules/js-bun-db/{fix → js}/safety/check.mjs +0 -0
- /package/rules/js-bun-redis/{fix → js}/imports/check.mjs +0 -0
- /package/rules/js-lint/{fix → js}/tooling/knip-canonical.json +0 -0
- /package/rules/js-lint/{fix → js}/tooling/oxlint-canonical-skeleton.json +0 -0
- /package/rules/js-lint/{fix → js}/tooling/oxlint-canonical.json +0 -0
- /package/rules/js-lint/{fix → js}/tooling/oxlint-rules.tsv +0 -0
- /package/rules/js-mssql/{fix → js}/deps/check.mjs +0 -0
- /package/rules/js-mssql/{fix → js}/deps/mssql-pool-scan.mjs +0 -0
- /package/rules/js-run/{fix → js}/runtime/bunyan-imports.mjs +0 -0
- /package/rules/js-run/{fix → js}/runtime/check-env-scan.mjs +0 -0
- /package/rules/js-run/{fix → js}/runtime/conn-file-rules.mjs +0 -0
- /package/rules/js-run/{fix → js}/runtime/conn-imports-scan.mjs +0 -0
- /package/rules/js-run/{fix → js}/runtime/promise-settimeout-scan.mjs +0 -0
- /package/rules/k8s/{fix → js}/kubescape_exceptions/template/.kubescape-exceptions.json.snippet.json +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/test/{fix → js}/location/check.mjs +0 -0
- /package/rules/vue/{fix → js}/packages/vue-forbidden-imports.mjs +0 -0
package/rules/abie/abie.mdc
CHANGED
|
@@ -133,12 +133,12 @@ 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
|
-
**Перевірка `
|
|
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-` відповідно.
|
|
140
140
|
|
|
141
|
-
Загальне правило про **внутрішній** URL (не публічний домен) для `HASURA_GRAPHQL_ENDPOINT` лишається у **`hasura.mdc`** (для nitra і abie) — `
|
|
141
|
+
Загальне правило про **внутрішній** URL (не публічний домен) для `HASURA_GRAPHQL_ENDPOINT` лишається у **`hasura.mdc`** (для nitra і abie) — `rules/hasura/fix.mjs` приймає кластерний DNS-формат `<cluster>.internal`.
|
|
142
142
|
|
|
143
143
|
## `@nitra/abie-docs` у `devDependencies`
|
|
144
144
|
|
|
@@ -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
|
|
163
|
+
Підмножину пер-документних правил продубльовано як rego-полісі у **`npm/rules/abie/policy/`** (запускається через **`bun run lint-rego`** для `*_test.rego` юніт-тестів і через **`npx @nitra/cursor fix 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,12 +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 / FS-логіка лишається у JS-частинах (`
|
|
173
|
+
Cross-file / FS-логіка лишається у JS-частинах (`js/<concern>/check.mjs`) — Rego не читає файлову систему й не робить cross-document резолюцію:
|
|
174
174
|
|
|
175
|
-
- парність HCP↔Deployment у каталозі та modeline `hc.yaml` — `
|
|
176
|
-
- валідація ua-overlay JSON6902 patches на HTTPRoute + аналіз cross-namespace `backendRefs` у пакетах — `
|
|
177
|
-
- ua-overlay JSON6902 patch на `Deployment.nodeSelector` (`preem: false`) — `
|
|
178
|
-
- env→cluster DNS (`*.dev.env` / `*.ua.env`) — `
|
|
179
|
-
- скан артефактів Firebase Hosting у підкаталогах першого рівня — `
|
|
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
180
|
|
|
181
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,19 @@
|
|
|
1
|
+
import { runStandardRule } from '../../scripts/utils/run-standard-rule.mjs'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Запускає правило: applies → JS-concerns → policy → mdc-refs (через runStandardRule).
|
|
5
|
+
* Library mode: викликається CLI orchestration через `import + run(ctx)`.
|
|
6
|
+
* @param {import('../../scripts/utils/run-standard-rule.mjs').RuleContext} [ctx] контекст прогону (walkCache тощо)
|
|
7
|
+
* @returns {Promise<number>} 0 — OK, 1 — порушення
|
|
8
|
+
*/
|
|
9
|
+
export function run(ctx) {
|
|
10
|
+
return runStandardRule(import.meta.dirname, ctx)
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
if (import.meta.main) {
|
|
14
|
+
// Standalone: bun rules/<id>/fix.mjs — повний еквівалент `npx @nitra/cursor fix <id>`
|
|
15
|
+
// (config-loading + whitelist + summary). Дві ролі fix.mjs: library (run) + standalone (main).
|
|
16
|
+
const { runRuleCli } = await import('../../scripts/utils/run-rule-cli.mjs')
|
|
17
|
+
// eslint-disable-next-line unicorn/no-process-exit -- standalone entry-point має повертати exit-code для CI/IDE
|
|
18
|
+
process.exit(await runRuleCli(import.meta.dirname))
|
|
19
|
+
}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
# `spec.template.spec.nodeSelector.preem` зі значенням, що вважається істинним
|
|
3
3
|
# (boolean `true` або рядок `"true"` без урахування регістру). Overlay ua далі
|
|
4
4
|
# підміняє селектор JSON6902-патчем на `preem: false`
|
|
5
|
-
# (див. `
|
|
5
|
+
# (див. `js/ua_node_selector/check.mjs`).
|
|
6
6
|
#
|
|
7
7
|
# Запуск (локально, лише для одного base-YAML з Deployment):
|
|
8
8
|
# conftest test path/to/k8s/base/deployment.yaml \
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
#
|
|
12
12
|
# Cross-file gating: шлях `…/k8s/.../base/…` фільтрується через
|
|
13
13
|
# `policy/base_deployment_preem/target.json` (glob). Rule-level applies-гейт —
|
|
14
|
-
# `
|
|
14
|
+
# `js/applies/check.mjs` (поле `rules` у `.n-cursor.json`).
|
|
15
15
|
#
|
|
16
16
|
# Структура каталогу збігається зі шляхом пакету (regal: directory-package-mismatch).
|
|
17
17
|
# Конвенція проєкту — `import rego.v1` + multi-value `deny contains msg if { … }`
|
|
@@ -18,8 +18,8 @@
|
|
|
18
18
|
#
|
|
19
19
|
# Cross-file gating: glob по `hc.yaml` у k8s-дереві — у
|
|
20
20
|
# `policy/health_check_policy/target.json`. FS-парність HCP↔Deployment та
|
|
21
|
-
# modeline `hc.yaml` — `
|
|
22
|
-
# `
|
|
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 { … }`
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
#
|
|
9
9
|
# Cross-file gating (саме шлях `…/k8s/.../base/...` визначає, чи застосовувати
|
|
10
10
|
# правило) задає glob у `policy/http_route_base/target.json`. Тут — лише
|
|
11
|
-
# валідація вмісту `spec.hostnames`. Rule-level applies-гейт — `
|
|
11
|
+
# валідація вмісту `spec.hostnames`. Rule-level applies-гейт — `js/applies/check.mjs`.
|
|
12
12
|
#
|
|
13
13
|
# Структура каталогу збігається зі шляхом пакету (regal: directory-package-mismatch).
|
|
14
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,19 @@
|
|
|
1
|
+
import { runStandardRule } from '../../scripts/utils/run-standard-rule.mjs'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Запускає правило: applies → JS-concerns → policy → mdc-refs (через runStandardRule).
|
|
5
|
+
* Library mode: викликається CLI orchestration через `import + run(ctx)`.
|
|
6
|
+
* @param {import('../../scripts/utils/run-standard-rule.mjs').RuleContext} [ctx] контекст прогону (walkCache тощо)
|
|
7
|
+
* @returns {Promise<number>} 0 — OK, 1 — порушення
|
|
8
|
+
*/
|
|
9
|
+
export function run(ctx) {
|
|
10
|
+
return runStandardRule(import.meta.dirname, ctx)
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
if (import.meta.main) {
|
|
14
|
+
// Standalone: bun rules/<id>/fix.mjs — повний еквівалент `npx @nitra/cursor fix <id>`
|
|
15
|
+
// (config-loading + whitelist + summary). Дві ролі fix.mjs: library (run) + standalone (main).
|
|
16
|
+
const { runRuleCli } = await import('../../scripts/utils/run-rule-cli.mjs')
|
|
17
|
+
// eslint-disable-next-line unicorn/no-process-exit -- standalone entry-point має повертати exit-code для CI/IDE
|
|
18
|
+
process.exit(await runRuleCli(import.meta.dirname))
|
|
19
|
+
}
|
|
@@ -116,7 +116,7 @@ async function checkHookScript(reporter, scriptName) {
|
|
|
116
116
|
function checkProjectSettings(reporter) {
|
|
117
117
|
const { pass, fail } = reporter
|
|
118
118
|
if (existsSync(PROJECT_SETTINGS_PATH)) {
|
|
119
|
-
pass(`${PROJECT_SETTINGS_PATH} є (Stop-hook перевіряє npx @nitra/cursor
|
|
119
|
+
pass(`${PROJECT_SETTINGS_PATH} є (Stop-hook перевіряє npx @nitra/cursor fix → adr.settings_json)`)
|
|
120
120
|
} else {
|
|
121
121
|
fail(`${PROJECT_SETTINGS_PATH} не існує — запусти \`npx @nitra/cursor\``)
|
|
122
122
|
}
|
package/rules/bun/bun.mdc
CHANGED
|
@@ -72,4 +72,4 @@ FROM oven/bun:alpine AS build-env
|
|
|
72
72
|
|
|
73
73
|
Якщо в **`.n-cursor.json`** у масиві **`rules`** є **`docker`**, у кореневому `package.json` **обов'язково** скрипт **`lint-docker`** (див. **`docker.mdc`**) і рядок **`bun run lint-docker`** у **`lint`**. Якщо є **`k8s`** — **обов'язково** **`lint-k8s`** і **`bun run lint-k8s`** у **`lint`** (див. **`k8s.mdc`**).
|
|
74
74
|
|
|
75
|
-
**Зворотній інваріант:** якщо правила **немає** в `rules` (або воно явно перенесене в **`disable-rules`**), скрипту **`lint-<id>`** у кореневому `package.json` бути **не може**, і ланцюжок агрегованого **`scripts.lint`** не має містити **`bun run lint-<id>`**. Інакше `bun run lint` падатиме на вимкненому правилі — `n-cursor lint-<id>` ігнорує `.n-cursor.json` і обходить дерево незалежно від `rules`/`disable-rules`. Для скриптів із кількома власниками (як **`lint-image`** — обслуговує і **`image-avif`**, і **`image-compress`**) скрипт лишається дозволеним, поки активний **хоч один** власник; зворотній інваріант тригериться лише коли в `rules` немає **жодного** з них. Перевірка — **`npx @nitra/cursor
|
|
75
|
+
**Зворотній інваріант:** якщо правила **немає** в `rules` (або воно явно перенесене в **`disable-rules`**), скрипту **`lint-<id>`** у кореневому `package.json` бути **не може**, і ланцюжок агрегованого **`scripts.lint`** не має містити **`bun run lint-<id>`**. Інакше `bun run lint` падатиме на вимкненому правилі — `n-cursor lint-<id>` ігнорує `.n-cursor.json` і обходить дерево незалежно від `rules`/`disable-rules`. Для скриптів із кількома власниками (як **`lint-image`** — обслуговує і **`image-avif`**, і **`image-compress`**) скрипт лишається дозволеним, поки активний **хоч один** власник; зворотній інваріант тригериться лише коли в `rules` немає **жодного** з них. Перевірка — **`npx @nitra/cursor fix bun`**.
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { runStandardRule } from '../../scripts/utils/run-standard-rule.mjs'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Запускає правило: applies → JS-concerns → policy → mdc-refs (через runStandardRule).
|
|
5
|
+
* Library mode: викликається CLI orchestration через `import + run(ctx)`.
|
|
6
|
+
* @param {import('../../scripts/utils/run-standard-rule.mjs').RuleContext} [ctx] контекст прогону (walkCache тощо)
|
|
7
|
+
* @returns {Promise<number>} 0 — OK, 1 — порушення
|
|
8
|
+
*/
|
|
9
|
+
export function run(ctx) {
|
|
10
|
+
return runStandardRule(import.meta.dirname, ctx)
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
if (import.meta.main) {
|
|
14
|
+
// Standalone: bun rules/<id>/fix.mjs — повний еквівалент `npx @nitra/cursor fix <id>`
|
|
15
|
+
// (config-loading + whitelist + summary). Дві ролі fix.mjs: library (run) + standalone (main).
|
|
16
|
+
const { runRuleCli } = await import('../../scripts/utils/run-rule-cli.mjs')
|
|
17
|
+
// eslint-disable-next-line unicorn/no-process-exit -- standalone entry-point має повертати exit-code для CI/IDE
|
|
18
|
+
process.exit(await runRuleCli(import.meta.dirname))
|
|
19
|
+
}
|
|
@@ -183,7 +183,7 @@ export async function check() {
|
|
|
183
183
|
}
|
|
184
184
|
|
|
185
185
|
if (existsSync('bunfig.toml')) {
|
|
186
|
-
pass('bunfig.toml є (структуру перевіряє npx @nitra/cursor
|
|
186
|
+
pass('bunfig.toml є (структуру перевіряє npx @nitra/cursor fix → bun.bunfig)')
|
|
187
187
|
} else {
|
|
188
188
|
fail('Відсутній bunfig.toml — створи з [install] linker = "hoisted" (bun.mdc)')
|
|
189
189
|
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { runStandardRule } from '../../scripts/utils/run-standard-rule.mjs'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Запускає правило: applies → JS-concerns → policy → mdc-refs (через runStandardRule).
|
|
5
|
+
* Library mode: викликається CLI orchestration через `import + run(ctx)`.
|
|
6
|
+
* @param {import('../../scripts/utils/run-standard-rule.mjs').RuleContext} [ctx] контекст прогону (walkCache тощо)
|
|
7
|
+
* @returns {Promise<number>} 0 — OK, 1 — порушення
|
|
8
|
+
*/
|
|
9
|
+
export function run(ctx) {
|
|
10
|
+
return runStandardRule(import.meta.dirname, ctx)
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
if (import.meta.main) {
|
|
14
|
+
// Standalone: bun rules/<id>/fix.mjs — повний еквівалент `npx @nitra/cursor fix <id>`
|
|
15
|
+
// (config-loading + whitelist + summary). Дві ролі fix.mjs: library (run) + standalone (main).
|
|
16
|
+
const { runRuleCli } = await import('../../scripts/utils/run-rule-cli.mjs')
|
|
17
|
+
// eslint-disable-next-line unicorn/no-process-exit -- standalone entry-point має повертати exit-code для CI/IDE
|
|
18
|
+
process.exit(await runRuleCli(import.meta.dirname))
|
|
19
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Порт перевірки версії `@capacitor/core` з `npm/scripts/
|
|
1
|
+
# Порт перевірки версії `@capacitor/core` з `npm/scripts/rules/capacitor/fix.mjs`
|
|
2
2
|
# (capacitor.mdc) — мінімальна мажорна версія = 8.
|
|
3
3
|
#
|
|
4
4
|
# Запуск (локально, у пакеті з Capacitor):
|
|
@@ -10,8 +10,8 @@
|
|
|
10
10
|
# Підтримує `^8.0.0`, `>=8`, `8.x`, `workspace:*` тощо.
|
|
11
11
|
#
|
|
12
12
|
# Цей порт спрощує JS-логіку — повна семантика OR-діапазонів (`a || b`) і нижня
|
|
13
|
-
# межа діапазону лишається в JS (`
|
|
14
|
-
# JS-перевірка лишилась authoritative й бігає через `npx @nitra/cursor
|
|
13
|
+
# межа діапазону лишається в JS (`rules/capacitor/fix.mjs`: `capacitorVersionRangeMinMajor`).
|
|
14
|
+
# JS-перевірка лишилась authoritative й бігає через `npx @nitra/cursor fix capacitor`;
|
|
15
15
|
# ця Rego — швидкий gate для одиничного `package.json` (наприклад через IDE).
|
|
16
16
|
#
|
|
17
17
|
# FS-сканування пакетів через workspaces, iOS-специфічна логіка (Podfile), вибір
|
|
@@ -10,7 +10,7 @@ alwaysApply: true
|
|
|
10
10
|
|
|
11
11
|
1. **`version`** у `<ws>/package.json` (або `[project].version` у `pyproject.toml`) → **patch +1** відносно `git show HEAD:<ws>/package.json`, якщо ще не піднято.
|
|
12
12
|
2. **`CHANGELOG.md`** того workspace → **нова** секція `## [версія] - YYYY-MM-DD` **зверху** (не bullet-и в стару версію).
|
|
13
|
-
3. **`npx @nitra/cursor
|
|
13
|
+
3. **`npx @nitra/cursor fix changelog`** (у репо `@nitra/cursor`: `bun ./npm/bin/n-cursor.js check changelog`) → exit **`0`**.
|
|
14
14
|
|
|
15
15
|
**Тригер шляхів (приклади):** `npm/**`, `packages/foo/**`, будь-який каталог з власним `package.json` / `pyproject.toml`, куди потрапили правки.
|
|
16
16
|
|
|
@@ -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,19 @@
|
|
|
1
|
+
import { runStandardRule } from '../../scripts/utils/run-standard-rule.mjs'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Запускає правило: applies → JS-concerns → policy → mdc-refs (через runStandardRule).
|
|
5
|
+
* Library mode: викликається CLI orchestration через `import + run(ctx)`.
|
|
6
|
+
* @param {import('../../scripts/utils/run-standard-rule.mjs').RuleContext} [ctx] контекст прогону (walkCache тощо)
|
|
7
|
+
* @returns {Promise<number>} 0 — OK, 1 — порушення
|
|
8
|
+
*/
|
|
9
|
+
export function run(ctx) {
|
|
10
|
+
return runStandardRule(import.meta.dirname, ctx)
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
if (import.meta.main) {
|
|
14
|
+
// Standalone: bun rules/<id>/fix.mjs — повний еквівалент `npx @nitra/cursor fix <id>`
|
|
15
|
+
// (config-loading + whitelist + summary). Дві ролі fix.mjs: library (run) + standalone (main).
|
|
16
|
+
const { runRuleCli } = await import('../../scripts/utils/run-rule-cli.mjs')
|
|
17
|
+
// eslint-disable-next-line unicorn/no-process-exit -- standalone entry-point має повертати exit-code для CI/IDE
|
|
18
|
+
process.exit(await runRuleCli(import.meta.dirname))
|
|
19
|
+
}
|
package/rules/ci4/ci4.mdc
CHANGED
|
@@ -30,7 +30,7 @@ RAG витягує **фрагменти**, не цілі документи. Т
|
|
|
30
30
|
|
|
31
31
|
## Docs-as-Code
|
|
32
32
|
|
|
33
|
-
Документація живе у Git поруч із кодом, проходить **той самий Code Review**, версіонується і автоматично перевіряється у CI (лінтери Markdown, валідатори посилань, `npx @nitra/cursor
|
|
33
|
+
Документація живе у Git поруч із кодом, проходить **той самий Code Review**, версіонується і автоматично перевіряється у CI (лінтери Markdown, валідатори посилань, `npx @nitra/cursor fix`). Биті посилання й документація, що «не компілюється», — **блокуючий баг**, не косметика.
|
|
34
34
|
|
|
35
35
|
## Трасування як документація недетермінованої поведінки
|
|
36
36
|
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { runStandardRule } from '../../scripts/utils/run-standard-rule.mjs'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Запускає правило: applies → JS-concerns → policy → mdc-refs (через runStandardRule).
|
|
5
|
+
* Library mode: викликається CLI orchestration через `import + run(ctx)`.
|
|
6
|
+
* @param {import('../../scripts/utils/run-standard-rule.mjs').RuleContext} [ctx] контекст прогону (walkCache тощо)
|
|
7
|
+
* @returns {Promise<number>} 0 — OK, 1 — порушення
|
|
8
|
+
*/
|
|
9
|
+
export function run(ctx) {
|
|
10
|
+
return runStandardRule(import.meta.dirname, ctx)
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
if (import.meta.main) {
|
|
14
|
+
// Standalone: bun rules/<id>/fix.mjs — повний еквівалент `npx @nitra/cursor fix <id>`
|
|
15
|
+
// (config-loading + whitelist + summary). Дві ролі fix.mjs: library (run) + standalone (main).
|
|
16
|
+
const { runRuleCli } = await import('../../scripts/utils/run-rule-cli.mjs')
|
|
17
|
+
// eslint-disable-next-line unicorn/no-process-exit -- standalone entry-point має повертати exit-code для CI/IDE
|
|
18
|
+
process.exit(await runRuleCli(import.meta.dirname))
|
|
19
|
+
}
|
package/rules/docker/docker.mdc
CHANGED
|
@@ -7,7 +7,7 @@ alwaysApply: false
|
|
|
7
7
|
|
|
8
8
|
# Docker — hadolint
|
|
9
9
|
|
|
10
|
-
Для образів з Docker Hub — **`oven/bun`**, **`alpine`**, **`nginxinc/nginx-unprivileged`**, **`node`** — у **`FROM`** треба вказувати дзеркало GCR, а не pull напряму з Hub: **`mirror.gcr.io/oven/bun`**, **`mirror.gcr.io/library/alpine`**, **`mirror.gcr.io/nginxinc/nginx-unprivileged`**, **`mirror.gcr.io/library/node`**. Перевіряє **`
|
|
10
|
+
Для образів з Docker Hub — **`oven/bun`**, **`alpine`**, **`nginxinc/nginx-unprivileged`**, **`node`** — у **`FROM`** треба вказувати дзеркало GCR, а не pull напряму з Hub: **`mirror.gcr.io/oven/bun`**, **`mirror.gcr.io/library/alpine`**, **`mirror.gcr.io/nginxinc/nginx-unprivileged`**, **`mirror.gcr.io/library/node`**. Перевіряє **`rules/docker/fix.mjs`**, деталі в **`npm/rules/docker/js/lint/docker-mirror.mjs`**.
|
|
11
11
|
|
|
12
12
|
Також Dockerfile/Containerfile **має бути multistage build**: окремий build stage (залежності/компіляція) і окремий runtime stage. У фінальному stage дозволені лише мінімальні базові образи:
|
|
13
13
|
|
|
@@ -90,33 +90,33 @@ CMD ["./app"]
|
|
|
90
90
|
|
|
91
91
|
## Область
|
|
92
92
|
|
|
93
|
-
- Усі файли з іменем **`Dockerfile`** або **`Dockerfile.*`** (наприклад `Dockerfile.prod`) у репозиторії, крім ігнорованих каталогів (`node_modules`, `.git`, `dist`, …) — як у **`
|
|
93
|
+
- Усі файли з іменем **`Dockerfile`** або **`Dockerfile.*`** (наприклад `Dockerfile.prod`) у репозиторії, крім ігнорованих каталогів (`node_modules`, `.git`, `dist`, …) — як у **`rules/docker/fix.mjs`**.
|
|
94
94
|
- Також скрипт перевірки обробляє **`Containerfile`** та **`Containerfile.*`** (Podman / альтернативні імена), навіть якщо glob правила спрацьовує переважно на `Dockerfile*`.
|
|
95
95
|
|
|
96
96
|
## lint-docker
|
|
97
97
|
|
|
98
98
|
CLI **`hadolint`** приймає лише **явні шляхи** (`[DOCKERFILE...]` у **`hadolint --help`**); обхід репозиторію робить CLI **`n-cursor lint-docker`** (реалізація — **`npm/rules/docker/js/run.mjs`**).
|
|
99
99
|
|
|
100
|
-
**Область lint-docker (вужча, ніж `check docker`):** лише файли з іменем **`Dockerfile`** та **`*.Dockerfile`** (суфікс **`.dockerfile`** без урахування регістру, наприклад **`api.Dockerfile`**). Файли **`Dockerfile.prod`**, **`Containerfile`** тощо **не** входять у **`lint-docker`**; їх ловить **`check docker`** (`
|
|
100
|
+
**Область lint-docker (вужча, ніж `check docker`):** лише файли з іменем **`Dockerfile`** та **`*.Dockerfile`** (суфікс **`.dockerfile`** без урахування регістру, наприклад **`api.Dockerfile`**). Файли **`Dockerfile.prod`**, **`Containerfile`** тощо **не** входять у **`lint-docker`**; їх ловить **`check docker`** (`rules/docker/fix.mjs`).
|
|
101
101
|
|
|
102
|
-
Обхід: **`walkDir`** з тими самими пропусками каталогів, що й **`
|
|
102
|
+
Обхід: **`walkDir`** з тими самими пропусками каталогів, що й **`rules/docker/fix.mjs`**. Виклик **`hadolint`**: **`PATH`**, інакше **`docker run`** — спільна логіка **`npm/rules/docker/js/lint/docker-hadolint.mjs`**.
|
|
103
103
|
|
|
104
104
|
- Канон `package.json#scripts.lint-docker`: [package.json.snippet.json](./policy/package_json/template/package.json.snippet.json)
|
|
105
105
|
|
|
106
|
-
Якщо правило **`docker`** підключено в **`.n-cursor.json`** (масив **`rules`**), у **кореневому** `package.json` **обов'язково** мають бути скрипт **`lint-docker`** і виклик **`bun run lint-docker`** у агрегованому **`lint`** (див. **`bun.mdc`**). Це перевіряє **`npx @nitra/cursor
|
|
106
|
+
Якщо правило **`docker`** підключено в **`.n-cursor.json`** (масив **`rules`**), у **кореневому** `package.json` **обов'язково** мають бути скрипт **`lint-docker`** і виклик **`bun run lint-docker`** у агрегованому **`lint`** (див. **`bun.mdc`**). Це перевіряє **`npx @nitra/cursor fix bun`**.
|
|
107
107
|
|
|
108
108
|
Додай workflow **`.github/workflows/lint-docker.yml`** (гілки **`dev`** і **`main`**, лише **`.yml`**, узгоджено з **`ga.mdc`**):
|
|
109
109
|
|
|
110
110
|
- Канон: [lint-docker.yml.snippet.yml](./policy/lint_docker_yml/template/lint-docker.yml.snippet.yml)
|
|
111
111
|
|
|
112
|
-
Узгоджуй версію hadolint **v2.12.0** з **`HADOLINT_IMAGE`** у **`npm/rules/docker/
|
|
112
|
+
Узгоджуй версію hadolint **v2.12.0** з **`HADOLINT_IMAGE`** у **`npm/rules/docker/js/lint/docker-hadolint.mjs`**.
|
|
113
113
|
|
|
114
114
|
Кореневий скрипт **`lint`** (див. **`n-bun.mdc`**) **обов'язково** містить **`bun run lint-docker`**, коли в проєкті підключено правило **`docker`**.
|
|
115
115
|
|
|
116
116
|
## Запуск
|
|
117
117
|
|
|
118
118
|
1. **`bun run lint-docker`** — **`run-docker.mjs`**: **`Dockerfile`** та **`*.Dockerfile`** (див. **`lint-docker`**); у CI встанови hadolint (приклад у workflow).
|
|
119
|
-
2. **`npx @nitra/cursor
|
|
119
|
+
2. **`npx @nitra/cursor fix docker`** — **`rules/docker/fix.mjs`**, виклик hadolint як у **`docker-hadolint.mjs`** (**`PATH`** або **`docker run`** з **`hadolint/hadolint:v2.12.0`**).
|
|
120
120
|
3. Кореневий **`.hadolint.yaml`**: вимкнення правил, trusted registries — [документація](https://github.com/hadolint/hadolint#configure). Щоб не додавати **`# hadolint ignore=DL3007`** у кожному **`FROM`** з **`:latest`**, у корені репозиторію задати глобально:
|
|
121
121
|
|
|
122
122
|
```yaml title=".hadolint.yaml"
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { runStandardRule } from '../../scripts/utils/run-standard-rule.mjs'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Запускає правило: applies → JS-concerns → policy → mdc-refs (через runStandardRule).
|
|
5
|
+
* Library mode: викликається CLI orchestration через `import + run(ctx)`.
|
|
6
|
+
* @param {import('../../scripts/utils/run-standard-rule.mjs').RuleContext} [ctx] контекст прогону (walkCache тощо)
|
|
7
|
+
* @returns {Promise<number>} 0 — OK, 1 — порушення
|
|
8
|
+
*/
|
|
9
|
+
export function run(ctx) {
|
|
10
|
+
return runStandardRule(import.meta.dirname, ctx)
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
if (import.meta.main) {
|
|
14
|
+
// Standalone: bun rules/<id>/fix.mjs — повний еквівалент `npx @nitra/cursor fix <id>`
|
|
15
|
+
// (config-loading + whitelist + summary). Дві ролі fix.mjs: library (run) + standalone (main).
|
|
16
|
+
const { runRuleCli } = await import('../../scripts/utils/run-rule-cli.mjs')
|
|
17
|
+
// eslint-disable-next-line unicorn/no-process-exit -- standalone entry-point має повертати exit-code для CI/IDE
|
|
18
|
+
process.exit(await runRuleCli(import.meta.dirname))
|
|
19
|
+
}
|
|
@@ -5,12 +5,12 @@
|
|
|
5
5
|
* check docker, не обробляються Dockerfile.*, Containerfile тощо — лише канонічне ім’я
|
|
6
6
|
* Dockerfile та варіанти виду app.Dockerfile (регістр суфікса не важливий).
|
|
7
7
|
*
|
|
8
|
-
* Виклик hadolint — через ../
|
|
8
|
+
* Виклик hadolint — через ../js/lint/docker-hadolint.mjs (PATH або docker run).
|
|
9
9
|
*/
|
|
10
10
|
import { basename } from 'node:path'
|
|
11
11
|
|
|
12
12
|
import { isRunAsCli } from '../../../scripts/cli-entry.mjs'
|
|
13
|
-
import { lintDockerfileWithHadolint, posixRel } from '../
|
|
13
|
+
import { lintDockerfileWithHadolint, posixRel } from '../js/lint/docker-hadolint.mjs'
|
|
14
14
|
import { createCheckReporter } from '../../../scripts/utils/check-reporter.mjs'
|
|
15
15
|
import { loadCursorIgnorePaths } from '../../../scripts/utils/load-cursor-config.mjs'
|
|
16
16
|
import { walkDir } from '../../../scripts/utils/walkDir.mjs'
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
# Канон надходить через --data: { "template": { "snippet": ... } }
|
|
4
4
|
# Перевіряє ЛИШЕ зміст значення `scripts.lint-docker`, якщо ключ присутній.
|
|
5
5
|
# Умовну обовʼязковість (правило `docker` у `.n-cursor.json` → `scripts.lint-docker`
|
|
6
|
-
# зобовʼязаний існувати) перевіряє `
|
|
6
|
+
# зобовʼязаний існувати) перевіряє `rules/bun/fix.mjs` через cross-file логіку.
|
|
7
7
|
package docker.package_json
|
|
8
8
|
|
|
9
9
|
import rego.v1
|
package/rules/efes/efes.mdc
CHANGED
|
@@ -16,7 +16,7 @@ bun add -d @nitra/efes-docs
|
|
|
16
16
|
|
|
17
17
|
## Швидкий gate через conftest (Rego)
|
|
18
18
|
|
|
19
|
-
Пер-документні перевірки efes — rego-полісі у **`npm/rules/efes/policy/`** (запускається через **`npx @nitra/cursor
|
|
19
|
+
Пер-документні перевірки efes — rego-полісі у **`npm/rules/efes/policy/`** (запускається через **`npx @nitra/cursor fix efes`**; синтаксичний lint — через **`bun run lint-rego`**). Деталі шаблону — у **conftest.mdc** / **n-rego.mdc**.
|
|
20
20
|
|
|
21
21
|
Пакети (директорія в **`npm/rules/efes/policy/`** → namespace → що перевіряє):
|
|
22
22
|
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { runStandardRule } from '../../scripts/utils/run-standard-rule.mjs'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Запускає правило: applies → JS-concerns → policy → mdc-refs (через runStandardRule).
|
|
5
|
+
* Library mode: викликається CLI orchestration через `import + run(ctx)`.
|
|
6
|
+
* @param {import('../../scripts/utils/run-standard-rule.mjs').RuleContext} [ctx] контекст прогону (walkCache тощо)
|
|
7
|
+
* @returns {Promise<number>} 0 — OK, 1 — порушення
|
|
8
|
+
*/
|
|
9
|
+
export function run(ctx) {
|
|
10
|
+
return runStandardRule(import.meta.dirname, ctx)
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
if (import.meta.main) {
|
|
14
|
+
// Standalone: bun rules/<id>/fix.mjs — повний еквівалент `npx @nitra/cursor fix <id>`
|
|
15
|
+
// (config-loading + whitelist + summary). Дві ролі fix.mjs: library (run) + standalone (main).
|
|
16
|
+
const { runRuleCli } = await import('../../scripts/utils/run-rule-cli.mjs')
|
|
17
|
+
// eslint-disable-next-line unicorn/no-process-exit -- standalone entry-point має повертати exit-code для CI/IDE
|
|
18
|
+
process.exit(await runRuleCli(import.meta.dirname))
|
|
19
|
+
}
|
|
@@ -4,7 +4,7 @@ alwaysApply: true
|
|
|
4
4
|
version: '1.0'
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
-
Правило про **зворотний звʼязок до пакета `@nitra/cursor`**. Виконуючи скіл пакета (`n-lint`, `n-fix`, `n-taze`, `n-adr-normalize`, `n-llm-patch`, `n-publish-telegram`, `mdc-check`), агент проходить крізь правила `.cursor/rules/`, інструкції `SKILL.md` і програмні перевірки `npx @nitra/cursor
|
|
7
|
+
Правило про **зворотний звʼязок до пакета `@nitra/cursor`**. Виконуючи скіл пакета (`n-lint`, `n-fix`, `n-taze`, `n-adr-normalize`, `n-llm-patch`, `n-publish-telegram`, `mdc-check`), агент проходить крізь правила `.cursor/rules/`, інструкції `SKILL.md` і програмні перевірки `npx @nitra/cursor fix`. Саме тут видно, що в пакеті недопрацьовано: неоднозначна інструкція, відсутня перевірка, хибне спрацювання, порушення без автофіксу. Ця інформація цінна для розробників пакета, але без явного кроку зникає разом із сесією.
|
|
8
8
|
|
|
9
9
|
## Коли застосовувати
|
|
10
10
|
|
|
@@ -17,7 +17,7 @@ version: '1.0'
|
|
|
17
17
|
**Тертя** — усе, що ускладнило роботу скілу й стосується самого пакета `@nitra/cursor`, а не коду користувацького проєкту:
|
|
18
18
|
|
|
19
19
|
- неоднозначна чи неповна інструкція в `SKILL.md` або `.mdc`;
|
|
20
|
-
- правило вимагає поведінку, яку можна перевірити програмно, але `check
|
|
20
|
+
- правило вимагає поведінку, яку можна перевірити програмно, але програмної перевірки (`rules/<id>/js/<concern>/check.mjs` або `rules/<id>/policy/<concern>/*.rego`) для неї немає;
|
|
21
21
|
- хибне спрацювання перевірки (false positive);
|
|
22
22
|
- порушення, яке правило вимагає виправляти вручну, хоча реальний автофікс можливий;
|
|
23
23
|
- повторюваний патерн, який варто закодувати в правило чи скіл.
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { runStandardRule } from '../../scripts/utils/run-standard-rule.mjs'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Запускає правило: applies → JS-concerns → policy → mdc-refs (через runStandardRule).
|
|
5
|
+
* Library mode: викликається CLI orchestration через `import + run(ctx)`.
|
|
6
|
+
* @param {import('../../scripts/utils/run-standard-rule.mjs').RuleContext} [ctx] контекст прогону (walkCache тощо)
|
|
7
|
+
* @returns {Promise<number>} 0 — OK, 1 — порушення
|
|
8
|
+
*/
|
|
9
|
+
export function run(ctx) {
|
|
10
|
+
return runStandardRule(import.meta.dirname, ctx)
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
if (import.meta.main) {
|
|
14
|
+
// Standalone: bun rules/<id>/fix.mjs — повний еквівалент `npx @nitra/cursor fix <id>`
|
|
15
|
+
// (config-loading + whitelist + summary). Дві ролі fix.mjs: library (run) + standalone (main).
|
|
16
|
+
const { runRuleCli } = await import('../../scripts/utils/run-rule-cli.mjs')
|
|
17
|
+
// eslint-disable-next-line unicorn/no-process-exit -- standalone entry-point має повертати exit-code для CI/IDE
|
|
18
|
+
process.exit(await runRuleCli(import.meta.dirname))
|
|
19
|
+
}
|
package/rules/ga/fix.mjs
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { runStandardRule } from '../../scripts/utils/run-standard-rule.mjs'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Запускає правило: applies → JS-concerns → policy → mdc-refs (через runStandardRule).
|
|
5
|
+
* Library mode: викликається CLI orchestration через `import + run(ctx)`.
|
|
6
|
+
* @param {import('../../scripts/utils/run-standard-rule.mjs').RuleContext} [ctx] контекст прогону (walkCache тощо)
|
|
7
|
+
* @returns {Promise<number>} 0 — OK, 1 — порушення
|
|
8
|
+
*/
|
|
9
|
+
export function run(ctx) {
|
|
10
|
+
return runStandardRule(import.meta.dirname, ctx)
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
if (import.meta.main) {
|
|
14
|
+
// Standalone: bun rules/<id>/fix.mjs — повний еквівалент `npx @nitra/cursor fix <id>`
|
|
15
|
+
// (config-loading + whitelist + summary). Дві ролі fix.mjs: library (run) + standalone (main).
|
|
16
|
+
const { runRuleCli } = await import('../../scripts/utils/run-rule-cli.mjs')
|
|
17
|
+
// eslint-disable-next-line unicorn/no-process-exit -- standalone entry-point має повертати exit-code для CI/IDE
|
|
18
|
+
process.exit(await runRuleCli(import.meta.dirname))
|
|
19
|
+
}
|
package/rules/ga/lint/lint.mjs
CHANGED
|
@@ -2,13 +2,13 @@
|
|
|
2
2
|
* CLI-обгортка над канонічним `lint-ga` (ga.mdc): робить preflight на `shellcheck`, `uv` (для `uvx`)
|
|
3
3
|
* і `conftest` (для rego-полісі у `check-ga`),
|
|
4
4
|
* тоді послідовно виконує `bunx github-actionlint`, `uvx zizmor --offline --collect=workflows .` і
|
|
5
|
-
* делегує до `
|
|
5
|
+
* делегує до `rules/ga/fix.mjs::check()` — там і Rego-частина (через `runConftestBatch`),
|
|
6
6
|
* і JS cross-file перевірки правил `ga.mdc`.
|
|
7
7
|
*
|
|
8
8
|
* Plan B-патерн (rego-authoritative): Rego-полісі (`npm/policy/ga/`) запускає вже сам
|
|
9
|
-
* `
|
|
9
|
+
* `rules/ga/fix.mjs::check()` як перший крок — `lint-ga.mjs` про це не знає. Раніше `lint-ga.mjs` сам
|
|
10
10
|
* спавнив conftest для `ga.<name>` per-workflow і `ga.workflow_common` (PoC); тепер ця логіка
|
|
11
|
-
* централізована у `
|
|
11
|
+
* централізована у `rules/ga/fix.mjs`, тож одне джерело істини, без дублювання між
|
|
12
12
|
* `lint-ga` і `npx \@nitra/cursor check ga`.
|
|
13
13
|
*
|
|
14
14
|
* Без preflight `actionlint` (через `bunx github-actionlint`) мовчки пропускає shell-перевірки в
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
* `uv` потрібен для `uvx zizmor`. Якщо його нема — `uvx zizmor` падає неінформативно («command not
|
|
19
19
|
* found»); підказка з командою встановлення коротша й корисніша.
|
|
20
20
|
*
|
|
21
|
-
* `conftest` потрібен для `
|
|
21
|
+
* `conftest` потрібен для `rules/ga/fix.mjs::runAllGaRego` (`runConftestBatch`). Без preflight крок
|
|
22
22
|
* check-ga кидає виняток, який глобальний `catch` у `bin/n-cursor.js` раніше ковтав без логу —
|
|
23
23
|
* локально це виглядало як мовчазний exit 1.
|
|
24
24
|
*
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
*/
|
|
27
27
|
import { platform } from 'node:process'
|
|
28
28
|
|
|
29
|
-
import { check as checkGa } from '../
|
|
29
|
+
import { check as checkGa } from '../js/workflows/check.mjs'
|
|
30
30
|
import { resolveCmd } from '../../../scripts/utils/resolve-cmd.mjs'
|
|
31
31
|
import { runLintStep } from '../../../scripts/utils/run-lint-step.mjs'
|
|
32
32
|
import { withLock } from '../../../scripts/utils/with-lock.mjs'
|
|
@@ -137,7 +137,7 @@ function preflight(dep) {
|
|
|
137
137
|
* 1) preflight: `shellcheck`, `uv` (для `uvx zizmor`) і `conftest` (для check-ga); відсутній → exit 1;
|
|
138
138
|
* 2) `bunx github-actionlint`;
|
|
139
139
|
* 3) `uvx zizmor --offline --collect=workflows .`;
|
|
140
|
-
* 4) `
|
|
140
|
+
* 4) `rules/ga/fix.mjs::check()` — Rego-полісі (батч conftest з `npm/policy/ga/`) + JS cross-file
|
|
141
141
|
* перевірки правил `ga.mdc`. Це **те саме**, що робить `npx \@nitra/cursor check ga`, тож
|
|
142
142
|
* `lint-ga` тепер є суперсетом перевірки правила: external-tools + check.
|
|
143
143
|
*
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
#
|
|
3
3
|
# Порт `verifyNoDirectBunOrCache`, `verifyNoRunShellLineContinuationBackslash`,
|
|
4
4
|
# `verifyCheckoutBeforeLocalSetupBunDeps` та `validateConcurrencyOnRoot` з
|
|
5
|
-
# `npm/scripts/
|
|
5
|
+
# `npm/scripts/rules/ga/fix.mjs`. На відміну від `lint_ga`/`clean_ga_workflows`/
|
|
6
6
|
# `clean_merged_branch`/`git_ai`, цей пакет не привʼязаний до конкретного
|
|
7
7
|
# workflow — `conftest test` запускається на кожному файлі окремо з
|
|
8
8
|
# `--namespace ga.workflow_common`, і `input` — це окремий розпарсений YAML.
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { runStandardRule } from '../../scripts/utils/run-standard-rule.mjs'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Запускає правило: applies → JS-concerns → policy → mdc-refs (через runStandardRule).
|
|
5
|
+
* Library mode: викликається CLI orchestration через `import + run(ctx)`.
|
|
6
|
+
* @param {import('../../scripts/utils/run-standard-rule.mjs').RuleContext} [ctx] контекст прогону (walkCache тощо)
|
|
7
|
+
* @returns {Promise<number>} 0 — OK, 1 — порушення
|
|
8
|
+
*/
|
|
9
|
+
export function run(ctx) {
|
|
10
|
+
return runStandardRule(import.meta.dirname, ctx)
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
if (import.meta.main) {
|
|
14
|
+
// Standalone: bun rules/<id>/fix.mjs — повний еквівалент `npx @nitra/cursor fix <id>`
|
|
15
|
+
// (config-loading + whitelist + summary). Дві ролі fix.mjs: library (run) + standalone (main).
|
|
16
|
+
const { runRuleCli } = await import('../../scripts/utils/run-rule-cli.mjs')
|
|
17
|
+
// eslint-disable-next-line unicorn/no-process-exit -- standalone entry-point має повертати exit-code для CI/IDE
|
|
18
|
+
process.exit(await runRuleCli(import.meta.dirname))
|
|
19
|
+
}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Пошук tagged template **`gql\`…\``** у джерелах для правила graphql.mdc.
|
|
3
3
|
*
|
|
4
4
|
* Для **`.vue`** береться лише вміст `<script>` / `<script setup>` (паралельна реалізація екстрактора;
|
|
5
|
-
* аналог у `rules/vue/
|
|
5
|
+
* аналог у `rules/vue/js/packages/vue-forbidden-imports.mjs` — модулі не діляться кодом, щоб уникати
|
|
6
6
|
* cross-rule імпортів і тримати кожне правило самодостатнім).
|
|
7
7
|
* Семантику визначає **oxc-parser** (`program`): рекурсивний обхід AST, збіг лише для **Identifier** з іменем **`gql`** як тега шаблону.
|
|
8
8
|
*/
|