@7n/rules-lang-js 0.3.1 → 0.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +12 -0
- package/package.json +14 -4
- package/rules/bun/bunfig/bunfig.mdc +17 -0
- package/rules/bun/bunfig/bunfig.rego +29 -0
- package/rules/bun/bunfig/concern.json +9 -0
- package/rules/bun/bunfig/template/bunfig.toml.snippet.toml +2 -0
- package/rules/bun/docs/index.md +11 -0
- package/rules/bun/layout/concern.json +16 -0
- package/rules/bun/layout/docs/fix-layout.md +29 -0
- package/rules/bun/layout/docs/main.md +34 -0
- package/rules/bun/layout/fix-layout.mjs +63 -0
- package/rules/bun/layout/layout.mdc +60 -0
- package/rules/bun/layout/main.mjs +53 -0
- package/rules/bun/licensee/concern.json +7 -0
- package/rules/bun/licensee/docs/fix-licensee.md +27 -0
- package/rules/bun/licensee/docs/index.md +12 -0
- package/rules/bun/licensee/docs/main.md +30 -0
- package/rules/bun/licensee/fix-licensee.mjs +31 -0
- package/rules/bun/licensee/main.mjs +68 -0
- package/rules/bun/lint-surface/concern.json +3 -0
- package/rules/bun/lint-surface/lint-surface.mdc +13 -0
- package/rules/bun/main.json +1 -0
- package/rules/bun/main.mdc +11 -0
- package/rules/bun/package_json/concern.json +9 -0
- package/rules/bun/package_json/docs/fix-package_json.md +28 -0
- package/rules/bun/package_json/docs/index.md +9 -0
- package/rules/bun/package_json/fix-package_json.mjs +311 -0
- package/rules/bun/package_json/package_json.mdc +14 -0
- package/rules/bun/package_json/package_json.rego +64 -0
- package/rules/bun/package_json/template/package.json.deny.json +4 -0
- package/rules/js/check/check.mdc +26 -0
- package/rules/js/check/concern.json +19 -0
- package/rules/js/check/docs/eslint-config.md +56 -0
- package/rules/js/check/docs/fix-check.md +48 -0
- package/rules/js/check/docs/index.md +13 -0
- package/rules/js/check/docs/main.md +48 -0
- package/rules/js/check/eslint-config.mjs +262 -0
- package/rules/js/check/fix-check.mjs +82 -0
- package/rules/js/check/main.mjs +310 -0
- package/rules/js/dep-policy/concern.json +4 -0
- package/rules/js/dep-policy/dep-policy.mdc +36 -0
- package/rules/js/dep-policy/docs/main.md +35 -0
- package/rules/js/dep-policy/main.mjs +99 -0
- package/rules/js/docs/index.md +11 -0
- package/rules/js/eslint/concern.json +8 -0
- package/rules/js/eslint/docs/fix-eslint.md +50 -0
- package/rules/js/eslint/docs/fix-worker.md +31 -0
- package/rules/js/eslint/docs/index.md +11 -0
- package/rules/js/eslint/docs/main.md +35 -0
- package/rules/js/eslint/fix-eslint.mjs +160 -0
- package/rules/js/eslint/fix-worker.mjs +139 -0
- package/rules/js/eslint/main.mjs +115 -0
- package/rules/js/file-extensions/concern.json +3 -0
- package/rules/js/file-extensions/file-extensions.mdc +12 -0
- package/rules/js/jscpd_config/concern.json +11 -0
- package/rules/js/jscpd_config/docs/fix-jscpd_config.md +25 -0
- package/rules/js/jscpd_config/docs/index.md +9 -0
- package/rules/js/jscpd_config/fix-jscpd_config.mjs +3 -0
- package/rules/js/jscpd_config/jscpd_config.mdc +42 -0
- package/rules/js/jscpd_config/jscpd_config.rego +44 -0
- package/rules/js/jscpd_config/template/.jscpd.json.snippet.json +7 -0
- package/rules/js/jscpd_duplicates/concern.json +7 -0
- package/rules/js/jscpd_duplicates/docs/main.md +29 -0
- package/rules/js/jscpd_duplicates/main.mjs +69 -0
- package/rules/js/knip/concern.json +7 -0
- package/rules/js/knip/docs/main.md +31 -0
- package/rules/js/knip/knip.mdc +15 -0
- package/rules/js/knip/main.mjs +89 -0
- package/rules/js/lint-findings/concern.json +3 -0
- package/rules/js/lint-findings/docs/main.md +40 -0
- package/rules/js/lint-findings/main.mjs +125 -0
- package/rules/js/main.json +1 -0
- package/rules/js/main.mdc +18 -0
- package/rules/js/package_json/concern.json +9 -0
- package/rules/js/package_json/docs/fix-package_json.md +25 -0
- package/rules/js/package_json/docs/index.md +9 -0
- package/rules/js/package_json/fix-package_json.mjs +3 -0
- package/rules/js/package_json/package_json.mdc +15 -0
- package/rules/js/package_json/package_json.rego +142 -0
- package/rules/js/package_json/template/package.json.snippet.json +6 -0
- package/rules/js/tooling/concern.json +3 -0
- package/rules/js/tooling/data/tooling/knip-canonical.json +30 -0
- package/rules/js/tooling/data/tooling/oxlint-canonical.json +400 -0
- package/rules/js/tooling/docs/main.md +53 -0
- package/rules/js/tooling/main.mjs +183 -0
- package/rules/js/utils_imports/concern.json +4 -0
- package/rules/js/utils_imports/docs/main.md +50 -0
- package/rules/js/utils_imports/main.mjs +185 -0
- package/rules/js/utils_imports/utils_imports.mdc +15 -0
- package/rules/js/vscode_extensions/concern.json +11 -0
- package/rules/js/vscode_extensions/docs/fix-vscode_extensions.md +24 -0
- package/rules/js/vscode_extensions/docs/index.md +11 -0
- package/rules/js/vscode_extensions/fix-vscode_extensions.mjs +1 -0
- package/rules/js/vscode_extensions/template/extensions.json.snippet.json +6 -0
- package/rules/js/vscode_extensions/vscode_extensions.mdc +11 -0
- package/rules/js/vscode_extensions/vscode_extensions.rego +12 -0
- package/rules/js-bun-db/connection/concern.json +3 -0
- package/rules/js-bun-db/connection/connection.mdc +42 -0
- package/rules/js-bun-db/docs/index.md +11 -0
- package/rules/js-bun-db/lib/bun-sql-scan.mjs +1047 -0
- package/rules/js-bun-db/lib/docs/bun-sql-scan.md +63 -0
- package/rules/js-bun-db/lib/docs/index.md +11 -0
- package/rules/js-bun-db/main.json +1 -0
- package/rules/js-bun-db/main.mdc +8 -0
- package/rules/js-bun-db/package_json/concern.json +9 -0
- package/rules/js-bun-db/package_json/package_json.mdc +31 -0
- package/rules/js-bun-db/package_json/package_json.rego +15 -0
- package/rules/js-bun-db/package_json/template/package.json.deny.json +6 -0
- package/rules/js-bun-db/pg_format_identifiers/concern.json +3 -0
- package/rules/js-bun-db/pg_format_identifiers/pg_format_identifiers.mdc +104 -0
- package/rules/js-bun-db/safety/concern.json +4 -0
- package/rules/js-bun-db/safety/docs/main.md +34 -0
- package/rules/js-bun-db/safety/main.mjs +430 -0
- package/rules/js-bun-db/safety/safety.mdc +458 -0
- package/rules/js-bun-redis/docs/index.md +11 -0
- package/rules/js-bun-redis/imports/concern.json +4 -0
- package/rules/js-bun-redis/imports/docs/main.md +36 -0
- package/rules/js-bun-redis/imports/imports.mdc +47 -0
- package/rules/js-bun-redis/imports/main.mjs +88 -0
- package/rules/js-bun-redis/lib/docs/index.md +11 -0
- package/rules/js-bun-redis/lib/docs/redis-imports.md +227 -0
- package/rules/js-bun-redis/lib/redis-imports.mjs +130 -0
- package/rules/js-bun-redis/main.json +1 -0
- package/rules/js-bun-redis/main.mdc +8 -0
- package/rules/js-bun-redis/package_json/concern.json +9 -0
- package/rules/js-bun-redis/package_json/package_json.mdc +11 -0
- package/rules/js-bun-redis/package_json/package_json.rego +15 -0
- package/rules/js-bun-redis/package_json/template/package.json.deny.json +12 -0
- package/rules/js-mssql/deps/concern.json +4 -0
- package/rules/js-mssql/deps/docs/main.md +33 -0
- package/rules/js-mssql/deps/main.mjs +297 -0
- package/rules/js-mssql/docs/index.md +11 -0
- package/rules/js-mssql/lib/docs/index.md +11 -0
- package/rules/js-mssql/lib/docs/mssql-pool-scan.md +380 -0
- package/rules/js-mssql/lib/mssql-pool-scan.mjs +610 -0
- package/rules/js-mssql/main.json +1 -0
- package/rules/js-mssql/main.mdc +144 -0
- package/rules/js-mssql/mssql-tvp/concern.json +3 -0
- package/rules/js-mssql/mssql-tvp/mssql-tvp.mdc +77 -0
- package/rules/js-mssql/package_json/concern.json +9 -0
- package/rules/js-mssql/package_json/package_json.mdc +9 -0
- package/rules/js-mssql/package_json/package_json.rego +57 -0
- package/rules/js-run/configmap/concern.json +9 -0
- package/rules/js-run/configmap/configmap.mdc +37 -0
- package/rules/js-run/configmap/configmap.rego +21 -0
- package/rules/js-run/configmap/template/configmap.yaml.contains.yml +4 -0
- package/rules/js-run/docs/index.md +11 -0
- package/rules/js-run/jsconfig/concern.json +9 -0
- package/rules/js-run/jsconfig/docs/fix-jsconfig.md +28 -0
- package/rules/js-run/jsconfig/docs/index.md +9 -0
- package/rules/js-run/jsconfig/fix-jsconfig.mjs +119 -0
- package/rules/js-run/jsconfig/jsconfig.mdc +48 -0
- package/rules/js-run/jsconfig/jsconfig.rego +59 -0
- package/rules/js-run/jsconfig/template/jsconfig.json.snippet.json +10 -0
- package/rules/js-run/lib/bunyan-imports.mjs +98 -0
- package/rules/js-run/lib/check-env-scan.mjs +338 -0
- package/rules/js-run/lib/conn-file-rules.mjs +214 -0
- package/rules/js-run/lib/conn-imports-scan.mjs +154 -0
- package/rules/js-run/lib/docs/bunyan-imports.md +121 -0
- package/rules/js-run/lib/docs/check-env-scan.md +438 -0
- package/rules/js-run/lib/docs/conn-file-rules.md +304 -0
- package/rules/js-run/lib/docs/conn-imports-scan.md +208 -0
- package/rules/js-run/lib/docs/index.md +16 -0
- package/rules/js-run/lib/docs/promise-settimeout-scan.md +334 -0
- package/rules/js-run/lib/docs/temporal-scan.md +29 -0
- package/rules/js-run/lib/promise-settimeout-scan.mjs +128 -0
- package/rules/js-run/lib/temporal-scan.mjs +52 -0
- package/rules/js-run/main.json +1 -0
- package/rules/js-run/main.mdc +16 -0
- package/rules/js-run/package_json/concern.json +9 -0
- package/rules/js-run/package_json/package_json.mdc +44 -0
- package/rules/js-run/package_json/package_json.rego +37 -0
- package/rules/js-run/package_json/template/package.json.deny.json +22 -0
- package/rules/js-run/project-structure/concern.json +3 -0
- package/rules/js-run/project-structure/project-structure.mdc +11 -0
- package/rules/js-run/runtime/concern.json +12 -0
- package/rules/js-run/runtime/docs/fix-runtime.md +27 -0
- package/rules/js-run/runtime/docs/main.md +35 -0
- package/rules/js-run/runtime/fix-runtime.mjs +46 -0
- package/rules/js-run/runtime/main.mjs +496 -0
- package/rules/js-run/runtime/runtime.mdc +184 -0
- package/rules/js-run/scope/concern.json +3 -0
- package/rules/js-run/scope/scope.mdc +11 -0
- package/rules/npm-module/docs/index.md +11 -0
- package/rules/npm-module/emit_types_config/concern.json +9 -0
- package/rules/npm-module/emit_types_config/docs/fix-emit_types_config.md +25 -0
- package/rules/npm-module/emit_types_config/docs/index.md +9 -0
- package/rules/npm-module/emit_types_config/emit_types_config.mdc +43 -0
- package/rules/npm-module/emit_types_config/emit_types_config.rego +28 -0
- package/rules/npm-module/emit_types_config/fix-emit_types_config.mjs +5 -0
- package/rules/npm-module/emit_types_config/template/tsconfig.emit-types.json.snippet.json +9 -0
- package/rules/npm-module/header_doc_pointer/concern.json +5 -0
- package/rules/npm-module/header_doc_pointer/docs/main.md +40 -0
- package/rules/npm-module/header_doc_pointer/header_doc_pointer.mdc +18 -0
- package/rules/npm-module/header_doc_pointer/main.mjs +131 -0
- package/rules/npm-module/main.json +1 -0
- package/rules/npm-module/main.mdc +36 -0
- package/rules/npm-module/npm_package_json/concern.json +9 -0
- package/rules/npm-module/npm_package_json/docs/fix-npm_package_json.md +26 -0
- package/rules/npm-module/npm_package_json/docs/index.md +9 -0
- package/rules/npm-module/npm_package_json/fix-npm_package_json.mjs +5 -0
- package/rules/npm-module/npm_package_json/npm_package_json.mdc +57 -0
- package/rules/npm-module/npm_package_json/npm_package_json.rego +73 -0
- package/rules/npm-module/npm_package_json/template/package.json.snippet.json +1 -0
- package/rules/npm-module/package_structure/concern.json +5 -0
- package/rules/npm-module/package_structure/docs/main.md +37 -0
- package/rules/npm-module/package_structure/main.mjs +448 -0
- package/rules/npm-module/package_structure/package_structure.mdc +63 -0
- package/rules/npm-module/root_package_json/concern.json +9 -0
- package/rules/npm-module/root_package_json/docs/fix-root_package_json.md +25 -0
- package/rules/npm-module/root_package_json/docs/index.md +9 -0
- package/rules/npm-module/root_package_json/fix-root_package_json.mjs +5 -0
- package/rules/npm-module/root_package_json/root_package_json.mdc +41 -0
- package/rules/npm-module/root_package_json/root_package_json.rego +28 -0
- package/rules/npm-module/root_package_json/template/package.json.snippet.json +1 -0
- package/rules/npm-module/rule_meta/concern.json +8 -0
- package/rules/npm-module/rule_meta/docs/main.md +35 -0
- package/rules/npm-module/rule_meta/main.mjs +119 -0
- package/rules/npm-module/rule_meta/rule_meta.mdc +11 -0
- package/rules/npm-module/skill_meta/concern.json +5 -0
- package/rules/npm-module/skill_meta/docs/main.md +149 -0
- package/rules/npm-module/skill_meta/main.mjs +91 -0
- package/rules/npm-module/skill_meta/skill_meta.mdc +11 -0
- package/rules/tool-surface/docs/index.md +11 -0
- package/rules/tool-surface/main.json +6 -0
- package/rules/tool-surface/main.mdc +72 -0
- package/rules/vue/composition-api/composition-api.mdc +82 -0
- package/rules/vue/composition-api/concern.json +3 -0
- package/rules/vue/docs/index.md +11 -0
- package/rules/vue/lib/docs/index.md +11 -0
- package/rules/vue/lib/docs/vue-forbidden-imports.md +265 -0
- package/rules/vue/lib/vue-forbidden-imports.mjs +240 -0
- package/rules/vue/main.json +1 -0
- package/rules/vue/main.mdc +18 -0
- package/rules/vue/nheader-layout/concern.json +3 -0
- package/rules/vue/nheader-layout/nheader-layout.mdc +171 -0
- package/rules/vue/package_json/concern.json +9 -0
- package/rules/vue/package_json/package_json.mdc +30 -0
- package/rules/vue/package_json/package_json.rego +140 -0
- package/rules/vue/packages/concern.json +6 -0
- package/rules/vue/packages/docs/index.md +11 -0
- package/rules/vue/packages/docs/main.md +35 -0
- package/rules/vue/packages/main.mjs +575 -0
- package/rules/vue/packages/packages.mdc +56 -0
- package/rules/vue/quasar-ui/concern.json +3 -0
- package/rules/vue/quasar-ui/quasar-ui.mdc +32 -0
- package/rules/vue/structure/concern.json +3 -0
- package/rules/vue/structure/structure.mdc +101 -0
- package/rules/vue/testing/concern.json +3 -0
- package/rules/vue/testing/testing.mdc +40 -0
- package/rules/vue/tfm-translations/concern.json +7 -0
- package/rules/vue/tfm-translations/docs/main.md +29 -0
- package/rules/vue/tfm-translations/main.mjs +55 -0
- package/rules/vue/tfm-translations/tfm-translations.mdc +32 -0
- package/rules/vue/vite-config/concern.json +3 -0
- package/rules/vue/vite-config/vite-config.mdc +153 -0
- package/rules/vue/vite-env/concern.json +3 -0
- package/rules/vue/vite-env/vite-env.mdc +61 -0
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
## Структура монорепо та компактний пакет
|
|
2
|
+
|
|
3
|
+
Bun monorepo: workspace **`npm/`**, кореневий **`package.json`**, **`.github/workflows/`**; опційно **`demo/`**.
|
|
4
|
+
|
|
5
|
+
Мета — **максимально компактний** опублікований пакет: у npm потрапляє тільки те, що потрібно під час `require`/`import` користувачем.
|
|
6
|
+
|
|
7
|
+
- **`"files"` обовʼязковий** у `npm/package.json` як **whitelist** того, що публікується (без `"files"` npm пакує майже все — це антипатерн для цього правила).
|
|
8
|
+
- **Тести й фікстури не публікуються — через негативні glob-патерни у `"files"`.** Тести можна (і зазвичай зручніше) тримати **поруч з кодом** усередині шляхів, перелічених у `"files"` (наприклад `*.test.mjs` поруч з модулем чи `fixtures/` під `rules/<id>/js/`). Щоб вони не потрапляли у tarball, `"files"` **обовʼязково має містити негативні glob-патерни**, що їх виключають. Покрий усі форми тестового: фреймворк-тести (`bun:test`, `node:test`, `vitest`, `@jest/globals`, `mocha`, …), test-style каталоги (`tests/`, `__tests__/`, `fixtures/`, `__fixtures__/`, `spec/`, `test/`), файли за патернами `*.test.*` / `*.spec.*`. Орієнтовний набір: `"!**/*.test.*"`, `"!**/*.spec.*"`, `"!**/test-helpers.*"`, `"!**/fixtures/**"`, `"!**/__tests__/**"`. **Rego (`*_test.rego`):** за конвенцією conftest юніт-тест лежить поруч з полісі у тому самому `package` — `*_test.rego` усередині опублікованого `policy/` дозволені; якщо потрібна максимальна компактність, додай `"!**/*_test.rego"` явно (як у самому `@7n/rules`).
|
|
9
|
+
- **Лише runtime-залежності у `npm/package.json`.** `devDependencies` тримай у **кореневому** `package.json` монорепо — тоді `npm install @nitra/<pkg>` не тягне інструментарій, потрібний лише для розробки самого пакета.
|
|
10
|
+
|
|
11
|
+
Перевірки JS (`package_structure.mjs`):
|
|
12
|
+
|
|
13
|
+
- Наявність `package.json`, `npm/`, `npm/package.json`.
|
|
14
|
+
- Walk шляхів з `"files"` з застосуванням негативних patterns і скан залишку на тест-патерни (walking + AST). Якщо після застосування негативних patterns у tarball лишається test-style файл — `check` падає з вказівкою, який саме негативний glob треба додати у `"files"`.
|
|
15
|
+
|
|
16
|
+
## TypeScript declaration (`npm/types`)
|
|
17
|
+
|
|
18
|
+
Файл **`npm/package.json`** має містити **`"types"`** (шлях до головного `.d.ts` або `.d.mts` під **`./types/…`**) і запис **`"types"`** у **`files`**, щоб npm публікував декларації.
|
|
19
|
+
|
|
20
|
+
Генерація — через **`tsc`** і **`bunx -p typescript`** (окремий пакет **`typescript`** у `devDependencies` не потрібен).
|
|
21
|
+
|
|
22
|
+
### Варіант A: є вихідний **`.js`** під **`npm/src/`**
|
|
23
|
+
|
|
24
|
+
Якщо під **`npm/src`** (рекурсивно) є хоча б один файл **`.js`**:
|
|
25
|
+
|
|
26
|
+
- **`"types": "./types/index.d.ts"`**;
|
|
27
|
+
- у **hk** на **`pre-commit`** з каталогу **`npm/`** викликай:
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
bunx -p typescript tsc src/**/*.js --declaration --allowJs --emitDeclarationOnly --outDir types --skipLibCheck
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Якщо glob не розгортається — **`bash -O globstar`** або **`include`** у **`tsconfig`** з тими самими **`compilerOptions`**.
|
|
34
|
+
|
|
35
|
+
### Варіант B: немає **`npm/src/**/*.js`** (наприклад лише **`bin/`**, **`scripts/**/*.mjs`**)
|
|
36
|
+
|
|
37
|
+
Не створюй штучний **`src/index.js`**. Замість цього:
|
|
38
|
+
|
|
39
|
+
1. Додай **`npm/tsconfig.emit-types.json`** з **`include`** на реальні шляхи (`.js` / `.mjs`), **`compilerOptions`**: **`allowJs`**, **`declaration`**, **`emitDeclarationOnly`**, **`outDir`: `"types"`**, **`skipLibCheck`**: **`true`** (за потреби **`rootDir`**, **`module`**, **`moduleResolution`**).
|
|
40
|
+
2. Після першого **`tsc`** подивись, який **`.d.ts`** / **`.d.mts`** відповідає публічному API, і вкажи його в **`types`** (наприклад **`./types/bin/cli.d.ts`**).
|
|
41
|
+
3. У **hk** на **`pre-commit`** з **`npm/`** викликай **`tsc -p tsconfig.emit-types.json`**. Якщо через імпорти **TypeScript** все одно згенерує зайві **`.d.mts`** у **`types/`**, після **`tsc`** обрізай дерево до потрібного entrypoint (наприклад залиш лише **`types/bin/n-rules.d.ts`** через **`find`**), щоб у пакеті не збирались декларації внутрішніх модулів.
|
|
42
|
+
|
|
43
|
+
Файл **`tsconfig.emit-types.json`** тримай у репозиторії для **hk** / локальної генерації; у **`files`** його не додавай, якщо не хочеш публікувати його на **npm**.
|
|
44
|
+
|
|
45
|
+
## Git hooks: hk + pre-commit
|
|
46
|
+
|
|
47
|
+
У корені репозиторію — **`hk.pkl`** (або **`.config/hk.pkl`**) з **`["pre-commit"]`** і командою з відповідного варіанту (A або B) вище.
|
|
48
|
+
|
|
49
|
+
Після додавання **`hk.pkl`**: **`hk install`**.
|
|
50
|
+
|
|
51
|
+
## npm publish
|
|
52
|
+
|
|
53
|
+
**`npm-publish.yml`:** push у **`main`**, **`on.push.paths`** з **`npm/**`**, **`JS-DevTools/npm-publish@v4.1.5`**, **`with.package: npm/package.json`**, **`permissions.id-token: write`** (OIDC на npm).
|
|
54
|
+
|
|
55
|
+
Workflow робить **release + publish** одним job (`release-publish`): крок **`Release (bump + CHANGELOG + tag)`** (`bunx n-rules release` — агрегує change-файли, bump `version`, генерує секцію `CHANGELOG.md`, ставить git-тег) виконується **перед** публікацією. Тому потрібні **`permissions.contents: write`** і **`persist-credentials: true`** з **`fetch-depth: 0`** на `checkout` (release пушить commit-back версії та тег), а також локальний composite **`./.github/actions/setup-bun-deps`** і крок `Configure git identity`. Це узгоджено з **`n-changelog`**: `version`/`CHANGELOG.md` змінює лише `n-rules release` у CI на `main`. Програмна перевірка (`npm_module.npm_publish_yml`) звіряє **весь канонічний сніпет** напряму (`target.json:"check":"template"`, generic deep-subset): усі поля й кроки сніпета (`on.push.paths`/`branches`, `concurrency`, `permissions.contents/id-token`, `checkout` з `persist-credentials/fetch-depth`, `setup-bun-deps`, `Configure git identity`, `Release`, publish-крок) **обовʼязкові**; зайві кроки/поля дозволені (subset-of), масиви матчаться за наявністю (порядок кроків не важить). Сніпет — єдине джерело істини: його редагування одразу змінює enforce, без правок rego й без міграторів.
|
|
56
|
+
|
|
57
|
+
- Канон: [npm-publish.yml.snippet.yml](./policy/npm_publish_yml/template/npm-publish.yml.snippet.yml)
|
|
58
|
+
|
|
59
|
+
## Канонічні конфіги
|
|
60
|
+
|
|
61
|
+
- Кореневий `package.json` (workspaces): [package.json.snippet.json](./policy/root_package_json/template/package.json.snippet.json)
|
|
62
|
+
- `npm/package.json` (whitelist `files` обовʼязково має містити `types`): [package.json.snippet.json](./policy/npm_package_json/template/package.json.snippet.json)
|
|
63
|
+
- `npm/tsconfig.emit-types.json` (canonical `compilerOptions` для emit-types): [tsconfig.emit-types.json.snippet.json](./policy/emit_types_config/template/tsconfig.emit-types.json.snippet.json)
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: JS Module
|
|
3
|
+
title: fix-root_package_json.mjs
|
|
4
|
+
resource: plugins/lang-js/rules/npm-module/root_package_json/fix-root_package_json.mjs
|
|
5
|
+
docgen:
|
|
6
|
+
crc: 7b0c2f93
|
|
7
|
+
model: openai-codex/gpt-5.4-mini
|
|
8
|
+
score: 100
|
|
9
|
+
issues: judge:inaccurate:0.97
|
|
10
|
+
judgeModel: openai-codex/gpt-5.4-mini
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## Огляд
|
|
14
|
+
|
|
15
|
+
`patterns` перевіряє кореневий `package.json` на відповідність еталонному шаблону npm-module і використовується для контролю очікуваної структури цього конфіга. Публічна функція: `patterns`. Конфіг, на який спирається код: `package.json`.
|
|
16
|
+
|
|
17
|
+
## Поведінка
|
|
18
|
+
|
|
19
|
+
1. `patterns` визначає набір правил, які звіряють кореневий `package.json` з еталонним шаблоном для npm-module.
|
|
20
|
+
2. Кожне правило в цьому наборі націлене на `package.json` і використовується для вирівнювання кореневого конфіга з очікуваною структурою проєкту.
|
|
21
|
+
3. `patterns` потрібен, щоб централізовано підтримувати однаковий формат root `package.json` у межах цього типу пакета.
|
|
22
|
+
|
|
23
|
+
## Гарантії поведінки
|
|
24
|
+
|
|
25
|
+
- Read-only: не виконує операцій запису (ФС/БД).
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: Directory Index
|
|
3
|
+
title: npm/rules/npm-module/root_package_json
|
|
4
|
+
resource: plugins/lang-js/rules/npm-module/root_package_json/
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
| Файл | Тип |
|
|
8
|
+
| ----------------------------------------------------- | --------- |
|
|
9
|
+
| [fix-root_package_json.mjs](fix-root_package_json.md) | JS Module |
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
## Rego-gate: валідація кореневого `package.json`
|
|
2
|
+
|
|
3
|
+
Rego-пакет: `npm-module.root_package_json`
|
|
4
|
+
|
|
5
|
+
Цільовий файл: `package.json` (корінь репозиторію)
|
|
6
|
+
|
|
7
|
+
### Що перевіряється
|
|
8
|
+
|
|
9
|
+
Subset-of перевірка масиву `workspaces`: кожне значення з канонічного сніпету має бути присутнє у `workspaces`. За замовчуванням обовʼязковий елемент — `"npm"`.
|
|
10
|
+
|
|
11
|
+
Якщо `workspaces` відсутнє або не є масивом — окрема deny-помилка.
|
|
12
|
+
|
|
13
|
+
Канонічний сніпет: [package.json.snippet.json](./template/package.json.snippet.json)
|
|
14
|
+
|
|
15
|
+
Решта перевірок кореневого `package.json` (заборонені поля, devDeps лише `@nitra/*`) — у пакеті `bun.package_json`. FS-перевірки (наявність директорії `npm/`, `npm/package.json`) — у JS.
|
|
16
|
+
|
|
17
|
+
### Приклади
|
|
18
|
+
|
|
19
|
+
✓ Правильно — `workspaces` містить `"npm"`:
|
|
20
|
+
|
|
21
|
+
```json
|
|
22
|
+
{ "workspaces": ["npm"] }
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
✓ Правильно — `workspaces` містить `"npm"` разом з іншими:
|
|
26
|
+
|
|
27
|
+
```json
|
|
28
|
+
{ "workspaces": ["demo", "npm", "tests"] }
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
✗ Неправильно — `workspaces` відсутній:
|
|
32
|
+
|
|
33
|
+
```json
|
|
34
|
+
{ "name": "monorepo" }
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
✗ Неправильно — `workspaces` без `"npm"`:
|
|
38
|
+
|
|
39
|
+
```json
|
|
40
|
+
{ "workspaces": ["demo"] }
|
|
41
|
+
```
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# Перевірка кореневого `package.json` для npm-module (npm-module.mdc).
|
|
2
|
+
#
|
|
3
|
+
# Канон надходить через --data: { "template": { "snippet": ... } }
|
|
4
|
+
# Структура --data сформована з template/package.json.snippet.json.
|
|
5
|
+
# Snippet-array subset-of: кожне значення з template-масиву має бути у input-масиві.
|
|
6
|
+
# Решта кореневих `package.json`-перевірок (заборонені поля, devDeps лише @nitra/*)
|
|
7
|
+
# — у `bun.package_json`. FS-перевірки (наявність каталогу `npm/`, `npm/package.json`)
|
|
8
|
+
# — у JS.
|
|
9
|
+
package npm_module.root_package_json
|
|
10
|
+
|
|
11
|
+
import rego.v1
|
|
12
|
+
|
|
13
|
+
# Поле має бути масивом — інакше окрема deny.
|
|
14
|
+
deny contains msg if {
|
|
15
|
+
some field in object.keys(data.template.snippet)
|
|
16
|
+
not is_array(object.get(input, field, null))
|
|
17
|
+
msg := sprintf("package.json: масив %s відсутній або не масив (npm-module.mdc)", [field])
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
# Subset-of: кожне значення з template має бути в input-масиві.
|
|
21
|
+
deny contains msg if {
|
|
22
|
+
some field, expected_values in data.template.snippet
|
|
23
|
+
is_array(object.get(input, field, null))
|
|
24
|
+
actual_set := {v | some v in input[field]}
|
|
25
|
+
some required in expected_values
|
|
26
|
+
not required in actual_set
|
|
27
|
+
msg := sprintf("package.json: %s має містити %q (npm-module.mdc)", [field, required])
|
|
28
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{ "workspaces": ["npm"] }
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: JS Module
|
|
3
|
+
title: main.mjs
|
|
4
|
+
resource: plugins/lang-js/rules/npm-module/rule_meta/main.mjs
|
|
5
|
+
docgen:
|
|
6
|
+
crc: c7424bda
|
|
7
|
+
model: omlx/gemma-4-e4b-it-OptiQ-4bit
|
|
8
|
+
score: 95
|
|
9
|
+
issues: anchor-miss:(scripts.mdc),judge:inaccurate:0.98
|
|
10
|
+
judgeModel: openai-codex/gpt-5.4-mini
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## Огляд
|
|
14
|
+
|
|
15
|
+
Lint-детектор concern-а `npm-module/rule_meta`: валідує метадані кожного правила у `npm/rules/<id>/` — файл `main.json` та супутні конвенції каталогу правила.
|
|
16
|
+
|
|
17
|
+
## Поведінка
|
|
18
|
+
|
|
19
|
+
1. Якщо `npm/rules/` відсутній — pass (немає правил для валідації).
|
|
20
|
+
2. Для кожної теки правила:
|
|
21
|
+
- `auto.md` є пережитком — якщо файл лишився, порушення (метадані тепер у `main.json`).
|
|
22
|
+
- `main.mdc` обовʼязковий (канон scripts.mdc) — відсутність = порушення.
|
|
23
|
+
- `main.json` має існувати і бути валідним JSON-обʼєктом.
|
|
24
|
+
- Поле `auto` (опційне) має відповідати одній з форм: `"завжди"` / масив / `{ glob }` / `{ predicate }`; предикат має бути зареєстрований у `RULE_PREDICATES`.
|
|
25
|
+
- Поле `lint` заборонене: rule-level lint-scope скасовано (spec 2026-06-28-concern-lint-scope-design) — lint-поверхня декларується у `<rule>/<concern>/concern.json#lint`.
|
|
26
|
+
- Поле `llmFix` заборонене: opt-in-прапорця немає — fix-можливість концерну визначається наявністю `fix-*.mjs`/`fix-worker.mjs`.
|
|
27
|
+
3. Повертає `LintResult` зі списком порушень; валідні правила репортяться як pass.
|
|
28
|
+
|
|
29
|
+
## Публічний API
|
|
30
|
+
|
|
31
|
+
lint — перевіряє `main.json` усіх правил у `npm/rules/` і повертає `{ violations }`.
|
|
32
|
+
|
|
33
|
+
## Гарантії поведінки
|
|
34
|
+
|
|
35
|
+
- Read-only: не виконує операцій запису (ФС/БД).
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
/** @see ./docs/main.md */
|
|
2
|
+
import { existsSync, readdirSync } from 'node:fs'
|
|
3
|
+
import { join } from 'node:path'
|
|
4
|
+
|
|
5
|
+
import { createViolationReporter } from '@7n/rules/scripts/lib/lint-surface/violation-reporter.mjs'
|
|
6
|
+
import { parseRuleAutoSpec, readRuleMetaRaw } from '@7n/rules/scripts/lib/rule-meta.mjs'
|
|
7
|
+
import { RULE_PREDICATES } from '@7n/rules/scripts/lib/rule-predicates.mjs'
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Перевіряє поле `auto` у meta.json одного правила.
|
|
11
|
+
* @param {string} id ідентифікатор правила
|
|
12
|
+
* @param {Record<string, unknown>} raw сирий meta.json
|
|
13
|
+
* @param {ReturnType<typeof createViolationReporter>} reporter репортер
|
|
14
|
+
* @returns {boolean} true, якщо поле валідне (або відсутнє)
|
|
15
|
+
*/
|
|
16
|
+
function checkAutoField(id, raw, reporter) {
|
|
17
|
+
if (raw.auto === undefined) return true
|
|
18
|
+
const spec = parseRuleAutoSpec(raw.auto)
|
|
19
|
+
if (spec === null) {
|
|
20
|
+
const autoHint = 'нерозпізнане (очікується "завжди" / масив / {glob} / {predicate})'
|
|
21
|
+
reporter.fail(`rules/${id}: main.json.auto ${autoHint}`)
|
|
22
|
+
return false
|
|
23
|
+
}
|
|
24
|
+
if ('predicate' in spec && !Object.hasOwn(RULE_PREDICATES, spec.predicate)) {
|
|
25
|
+
reporter.fail(`rules/${id}: main.json — невідомий predicate "${spec.predicate}" (немає в RULE_PREDICATES)`)
|
|
26
|
+
return false
|
|
27
|
+
}
|
|
28
|
+
return true
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Забороняє залишкове поле `lint` у meta.json правила.
|
|
33
|
+
* Канон (spec 2026-06-28-concern-lint-scope-design): lint-scope живе у
|
|
34
|
+
* `<rule>/<concern>/concern.json#lint`, rule-level `main.json.lint` скасовано.
|
|
35
|
+
* @param {string} id ідентифікатор правила
|
|
36
|
+
* @param {Record<string, unknown>} raw сирий meta.json
|
|
37
|
+
* @param {ReturnType<typeof createViolationReporter>} reporter репортер
|
|
38
|
+
* @returns {boolean} true, якщо поле відсутнє
|
|
39
|
+
*/
|
|
40
|
+
function checkLintField(id, raw, reporter) {
|
|
41
|
+
if (raw.lint === undefined) return true
|
|
42
|
+
reporter.fail(`rules/${id}: main.json.lint скасовано — lint-scope декларується у <concern>/concern.json#lint`)
|
|
43
|
+
return false
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Забороняє залишкове поле `llmFix` у meta.json правила.
|
|
48
|
+
* Канон (scripts.mdc, spec 2026-06-28-concern-lint-scope-design): opt-in-прапорця
|
|
49
|
+
* llmFix немає — fix-можливість концерну визначається наявністю `fix-*.mjs`/`fix-worker.mjs`.
|
|
50
|
+
* @param {string} id ідентифікатор правила
|
|
51
|
+
* @param {Record<string, unknown>} raw сирий meta.json
|
|
52
|
+
* @param {ReturnType<typeof createViolationReporter>} reporter репортер
|
|
53
|
+
* @returns {boolean} true, якщо поле відсутнє
|
|
54
|
+
*/
|
|
55
|
+
function checkLlmFixField(id, raw, reporter) {
|
|
56
|
+
if (raw.llmFix === undefined) return true
|
|
57
|
+
reporter.fail(
|
|
58
|
+
`rules/${id}: main.json.llmFix скасовано — fix-можливість = наявність fix-*.mjs/fix-worker.mjs у концерні`
|
|
59
|
+
)
|
|
60
|
+
return false
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Валідує meta.json одного правила.
|
|
65
|
+
* @param {string} id ідентифікатор правила
|
|
66
|
+
* @param {string} ruleDir каталог правила
|
|
67
|
+
* @param {ReturnType<typeof createViolationReporter>} reporter репортер
|
|
68
|
+
* @returns {void}
|
|
69
|
+
*/
|
|
70
|
+
function checkRule(id, ruleDir, reporter) {
|
|
71
|
+
let ruleOk = true
|
|
72
|
+
|
|
73
|
+
if (existsSync(join(ruleDir, 'auto.md'))) {
|
|
74
|
+
reporter.fail(`rules/${id}: залишковий auto.md — видали (метадані тепер у main.json)`)
|
|
75
|
+
ruleOk = false
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// Канон (scripts.mdc): main.mdc — ОБОВ'ЯЗКОВИЙ у кожному npm/rules/<id>/.
|
|
79
|
+
if (!existsSync(join(ruleDir, 'main.mdc'))) {
|
|
80
|
+
reporter.fail(`rules/${id}: відсутній main.mdc — обов'язковий (scripts.mdc)`)
|
|
81
|
+
ruleOk = false
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
const raw = readRuleMetaRaw(ruleDir)
|
|
85
|
+
if (!raw) {
|
|
86
|
+
reporter.fail(`rules/${id}: відсутній або невалідний main.json`)
|
|
87
|
+
return
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
if (!checkAutoField(id, raw, reporter)) ruleOk = false
|
|
91
|
+
if (!checkLintField(id, raw, reporter)) ruleOk = false
|
|
92
|
+
if (!checkLlmFixField(id, raw, reporter)) ruleOk = false
|
|
93
|
+
|
|
94
|
+
if (ruleOk) {
|
|
95
|
+
reporter.pass(`rules/${id}: main.json валідний`)
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Валідує всі `npm/rules/<id>/meta.json`.
|
|
101
|
+
* @param {import('@7n/rules/scripts/lib/lint-surface/types.mjs').LintContext} ctx Контекст лінту (`cwd` тощо).
|
|
102
|
+
* @returns {Promise<import('@7n/rules/scripts/lib/lint-surface/types.mjs').LintResult>} Результат лінту зі списком violations.
|
|
103
|
+
*/
|
|
104
|
+
export function lint(ctx) {
|
|
105
|
+
const cwd = ctx.cwd
|
|
106
|
+
const reporter = createViolationReporter(ctx)
|
|
107
|
+
const rulesDir = join(cwd, 'npm', 'rules')
|
|
108
|
+
if (!existsSync(rulesDir)) {
|
|
109
|
+
reporter.pass('npm/rules/ відсутній — немає правил для валідації')
|
|
110
|
+
return Promise.resolve(reporter.result())
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
for (const entry of readdirSync(rulesDir, { withFileTypes: true })) {
|
|
114
|
+
if (!entry.isDirectory() || entry.name.startsWith('.')) continue
|
|
115
|
+
checkRule(entry.name, join(rulesDir, entry.name), reporter)
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
return Promise.resolve(reporter.result())
|
|
119
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
## Валідація `main.json` правил
|
|
2
|
+
|
|
3
|
+
Кожне правило у `npm/rules/<id>/` повинно мати коректний `main.json` (метадані правила).
|
|
4
|
+
|
|
5
|
+
Перевірки (`rule_meta.mjs`):
|
|
6
|
+
|
|
7
|
+
- **`main.mdc` обовʼязковий** у кожному `npm/rules/<id>/` — без нього `check` падає.
|
|
8
|
+
- **`auto.md` є пережитком** — якщо такий файл залишився, `check` вимагає його видалити (метадані тепер у `main.json`).
|
|
9
|
+
- **`main.json` має бути валідним JSON** із коректними полями:
|
|
10
|
+
- **`auto`** (опційне): `"завжди"` / масив glob-рядків / `{ glob }` / `{ predicate }`. Якщо `predicate` вказано — він має бути зареєстрований у `RULE_PREDICATES`.
|
|
11
|
+
- **`lint` заборонене**: rule-level scope скасовано — lint-поверхня декларується per-concern у `<rule>/<concern>/concern.json#lint` (spec 2026-06-28-concern-lint-scope-design).
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: JS Module
|
|
3
|
+
title: main.mjs
|
|
4
|
+
resource: plugins/lang-js/rules/npm-module/skill_meta/main.mjs
|
|
5
|
+
docgen:
|
|
6
|
+
crc: 1bfaac0d
|
|
7
|
+
model: omlx/gemma-4-e4b-it-OptiQ-4bit
|
|
8
|
+
score: 100
|
|
9
|
+
issues: judge:inaccurate:0.99
|
|
10
|
+
judgeModel: openai-codex/gpt-5.4-mini
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## Огляд
|
|
14
|
+
|
|
15
|
+
system_message:
|
|
16
|
+
You are an expert coding assistant operating inside pi, a coding agent harness. You help users by reading files, executing commands, editing code, and writing new files.
|
|
17
|
+
|
|
18
|
+
Available tools:
|
|
19
|
+
(none)
|
|
20
|
+
|
|
21
|
+
In addition to the tools above, you may have access to other custom tools depending on the project.
|
|
22
|
+
|
|
23
|
+
Guidelines:
|
|
24
|
+
|
|
25
|
+
- Be concise in your responses
|
|
26
|
+
- Show file paths clearly when working with files
|
|
27
|
+
|
|
28
|
+
Pi documentation (read only when the user asks about pi itself, its SDK, extensions, themes, skills, or TUI):
|
|
29
|
+
|
|
30
|
+
- Main documentation: /Users/vitalii/www/nitra/cursor/node_modules/@earendil-works/pi-coding-agent/README.md
|
|
31
|
+
- Additional docs: /Users/vitalii/www/nitra/cursor/node_modules/@earendil-works/pi-coding-agent/docs
|
|
32
|
+
- Examples: /Users/vitalii/www/nitra/cursor/node_modules/@earendil-works/pi-coding-agent/examples (extensions, custom tools, SDK)
|
|
33
|
+
- When reading pi docs or examples, resolve docs/... under Additional docs and examples/... under Examples, not the current working directory
|
|
34
|
+
- When asked about: extensions (docs/extensions.md, examples/extensions/), themes (docs/themes.md), skills (docs/skills.md), prompt templates (docs/prompt-templates.md), TUI components (docs/tui.md), keybindings (docs/keybindings.md), SDK integrations (docs/sdk.md), custom providers (docs/custom-provider.md), adding models (docs/models.md), pi packages (docs/packages.md)
|
|
35
|
+
- When working on pi topics, read the pi .md files completely and follow .md cross-references before implementing
|
|
36
|
+
- Always read pi .md files completely and follow links to related docs (e.g., tui.md for TUI API details)
|
|
37
|
+
|
|
38
|
+
<project_context>
|
|
39
|
+
Project-specific instructions and guidelines:
|
|
40
|
+
|
|
41
|
+
<project_instructions path="/Users/vitalii/www/nitra/cursor/AGENTS.md">
|
|
42
|
+
|
|
43
|
+
# AGENTS.md version: '1.0'
|
|
44
|
+
|
|
45
|
+
## Purpose
|
|
46
|
+
|
|
47
|
+
This file is the entry point for all AI agents working with this repository.
|
|
48
|
+
|
|
49
|
+
## Rule source
|
|
50
|
+
|
|
51
|
+
The primary development rules are stored in the Cursor rules directory:
|
|
52
|
+
|
|
53
|
+
- .cursor/rules/conftest.mdc
|
|
54
|
+
- .cursor/rules/dev-dep.mdc
|
|
55
|
+
- .cursor/rules/n-adr.mdc
|
|
56
|
+
- .cursor/rules/n-bun.mdc
|
|
57
|
+
- .cursor/rules/n-changelog.mdc
|
|
58
|
+
- .cursor/rules/n-ci4.mdc
|
|
59
|
+
- .cursor/rules/n-doc-files.mdc
|
|
60
|
+
- .cursor/rules/n-feedback.mdc
|
|
61
|
+
- .cursor/rules/n-ga.mdc
|
|
62
|
+
- .cursor/rules/n-js-run.mdc
|
|
63
|
+
- .cursor/rules/n-js.mdc
|
|
64
|
+
- .cursor/rules/n-npm-module.mdc
|
|
65
|
+
- .cursor/rules/n-python.mdc
|
|
66
|
+
- .cursor/rules/n-rego.mdc
|
|
67
|
+
- .cursor/rules/n-security.mdc
|
|
68
|
+
- .cursor/rules/n-style.mdc
|
|
69
|
+
- .cursor/rules/n-test.mdc
|
|
70
|
+
- .cursor/rules/n-text.mdc
|
|
71
|
+
- .cursor/rules/n-tool-surface.mdc
|
|
72
|
+
- .cursor/rules/n-vue.mdc
|
|
73
|
+
- .cursor/rules/n-worktree.mdc
|
|
74
|
+
- .cursor/rules/scripts.mdc
|
|
75
|
+
|
|
76
|
+
## Skills
|
|
77
|
+
|
|
78
|
+
- `.cursor/skills/mdc-check/SKILL.md` — Проаналізувати правило в npm/mdc: максимум перевірюваної логіки й деталей — у check-{id}.mjs з зрозумілими коментарями/JSDoc; у .mdc залишати людинозрозумілий зміст без дублювання алгоритму перевірки
|
|
79
|
+
- `.cursor/skills/n-adr-normalize/SKILL.md` — Ручний запуск ADR-нормалізації — обхід порогу й min-interval, прогон одного батчу чернеток через LLM, перегляд результату через git diff
|
|
80
|
+
- `.cursor/skills/n-doc-files/SKILL.md` — Обовʼязковий крок задачі (як lint): для кожного зміненого/нового кодового файлу (js/mjs/ts/vue/py) JS-оркестрована генерація лаконічної поведінкової української md-документації у теку docs/ поряд із кодом, зі звіркою застарілості за CRC у frontmatter
|
|
81
|
+
- `.cursor/skills/n-lint/SKILL.md` — Запустити дельта-лінт (npx @7n/rules lint) по змінених файлах vs origin, виправити порушення й підтвердити чистий вихід
|
|
82
|
+
- `.cursor/skills/n-llm-patch/SKILL.md` — Підготовка самодостатнього текстового промпта для іншого Claude/Cursor-агента — read-only аналіз CWD без жодних змін у поточному репо
|
|
83
|
+
- `.cursor/skills/n-publish-telegram/SKILL.md` — Підготовка матеріалу з поточного контексту для публікації в Telegram-каналі команди
|
|
84
|
+
- `.cursor/skills/n-taze/SKILL.md` — Оновлення версій модулів проекту з аналізом major-змін і автоматичним рефакторингом несумісного коду
|
|
85
|
+
|
|
86
|
+
## Commands
|
|
87
|
+
|
|
88
|
+
Generated from the root `package.json` on each `npx @7n/rules` sync. Prefer `bun run <script>` for project scripts.
|
|
89
|
+
|
|
90
|
+
- **Залежності**: `bun i`
|
|
91
|
+
- **test**: `bun run test`
|
|
92
|
+
- **start**: `bun run start`
|
|
93
|
+
- **Оновити правила та AGENTS.md** (після змін у правилах/шаблоні CLI): `npx @7n/rules`
|
|
94
|
+
- **Перевірки правил (programmatic)**: `npx @7n/rules fix`
|
|
95
|
+
- **knip (невикористані залежності та експорти)**: `bunx knip`
|
|
96
|
+
|
|
97
|
+
## Instructions for all agents
|
|
98
|
+
|
|
99
|
+
Before making changes, read the relevant rule files for the area you are working on.
|
|
100
|
+
|
|
101
|
+
## Інваріант після змін
|
|
102
|
+
|
|
103
|
+
`n-changelog.mdc` (alwaysApply) релевантне після **будь-якої** зміни файлів, не лише для релізу. Перед фінальною відповіддю виконай `npx @7n/rules fix changelog` (exit `0`) і познач результат рядком `Changelog: …` у відповіді.
|
|
104
|
+
|
|
105
|
+
## Priority
|
|
106
|
+
|
|
107
|
+
If rules conflict:
|
|
108
|
+
|
|
109
|
+
1. AGENTS.md
|
|
110
|
+
2. task-specific rule file
|
|
111
|
+
3. core rule file
|
|
112
|
+
|
|
113
|
+
## Language
|
|
114
|
+
|
|
115
|
+
Respond in Ukrainian.
|
|
116
|
+
Keep technical terms in English.
|
|
117
|
+
|
|
118
|
+
## Behavior
|
|
119
|
+
|
|
120
|
+
Do not ignore referenced rule files.
|
|
121
|
+
Explicitly follow repository conventions before proposing or applying changes.
|
|
122
|
+
|
|
123
|
+
</project_instructions>
|
|
124
|
+
</project_context>
|
|
125
|
+
|
|
126
|
+
## Поведінка
|
|
127
|
+
|
|
128
|
+
Поведінка:
|
|
129
|
+
|
|
130
|
+
1. Перевіряє наявність каталогу `npm/skills` у корені репозиторію. Якщо відсутній, операція завершується успіхом.
|
|
131
|
+
2. Ітерується по всім підкаталогах у `npm/skills`. Для кожного каталогу виконується перевірка відповідності метаданих скіла.
|
|
132
|
+
3. Для кожного скіла перевіряється, чи відсутній файл `auto.md`. Якщо знайдено, фіксується порушення, оскільки метадані мають знаходитися у `main.json`.
|
|
133
|
+
4. Зчитується вміст `main.json` скіла. Якщо файл відсутній або недійсний, фіксується порушення.
|
|
134
|
+
5. Виконується перевірка полів у `main.json` скіла:
|
|
135
|
+
- Перевіряється тип поля `worktree` — має бути булевим значенням.
|
|
136
|
+
- Якщо поле `auto` визначене, аналізується його значення на відповідність очікуваним форматам.
|
|
137
|
+
- Перевіряється тип поля `requireRoot` — має бути булевим значенням.
|
|
138
|
+
- Перевіряється узгодженість: якщо `worktree` дорівнює `true`, поле `requireRoot` не може бути `false`.
|
|
139
|
+
- Якщо поле `tier` визначене, воно має відповідати одному з визначених рівнів.
|
|
140
|
+
6. Якщо всі перевірки для скіла успішно пройдені, фіксується успішний статус для цього скіла.
|
|
141
|
+
7. Завершення виконання `main` та повернення коду виходу, що відображає кількість виявлених порушень.
|
|
142
|
+
|
|
143
|
+
## Публічний API
|
|
144
|
+
|
|
145
|
+
main — перевіряє, що всі файли `npm/skills/<id>/meta.json` відповідають встановленим вимогам.
|
|
146
|
+
|
|
147
|
+
## Гарантії поведінки
|
|
148
|
+
|
|
149
|
+
- Read-only: не виконує операцій запису (ФС/БД).
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/** @see ./docs/skill_meta.md */
|
|
2
|
+
import { existsSync, readdirSync } from 'node:fs'
|
|
3
|
+
import { join } from 'node:path'
|
|
4
|
+
|
|
5
|
+
import { createViolationReporter } from '@7n/rules/scripts/lib/lint-surface/violation-reporter.mjs'
|
|
6
|
+
import { SKILL_TIERS, parseSkillAutoSpec, readSkillMetaRaw } from '@7n/rules/scripts/lib/skill-meta.mjs'
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Перевіряє поля сирого meta.json одного скіла (без auto.md / відсутності файлу).
|
|
10
|
+
* @param {string} id ідентифікатор скіла
|
|
11
|
+
* @param {Record<string, unknown>} raw сирий meta.json
|
|
12
|
+
* @param {ReturnType<typeof createViolationReporter>} reporter репортер
|
|
13
|
+
* @returns {boolean} true, якщо всі поля валідні
|
|
14
|
+
*/
|
|
15
|
+
function checkSkillFields(id, raw, reporter) {
|
|
16
|
+
let ok = true
|
|
17
|
+
if (typeof raw.worktree !== 'boolean') {
|
|
18
|
+
reporter.fail(`skills/${id}: main.json.worktree має бути boolean`)
|
|
19
|
+
ok = false
|
|
20
|
+
}
|
|
21
|
+
if (raw.auto !== undefined && parseSkillAutoSpec(raw.auto) === null) {
|
|
22
|
+
reporter.fail(`skills/${id}: main.json.auto нерозпізнане — очікується "завжди" або непорожній масив правил`)
|
|
23
|
+
ok = false
|
|
24
|
+
}
|
|
25
|
+
if (raw.requireRoot !== undefined && typeof raw.requireRoot !== 'boolean') {
|
|
26
|
+
reporter.fail(`skills/${id}: main.json.requireRoot має бути boolean`)
|
|
27
|
+
ok = false
|
|
28
|
+
}
|
|
29
|
+
if (raw.worktree === true && raw.requireRoot === false) {
|
|
30
|
+
reporter.fail(
|
|
31
|
+
`skills/${id}: requireRoot:false суперечить worktree:true (worktree вже вимагає кореня — прибери поле)`
|
|
32
|
+
)
|
|
33
|
+
ok = false
|
|
34
|
+
}
|
|
35
|
+
if (raw.tier !== undefined && !(typeof raw.tier === 'string' && SKILL_TIERS.includes(raw.tier))) {
|
|
36
|
+
const tierList = SKILL_TIERS.map(t => `"${t}"`).join(' | ')
|
|
37
|
+
reporter.fail(`skills/${id}: main.json.tier має бути ${tierList}`)
|
|
38
|
+
ok = false
|
|
39
|
+
}
|
|
40
|
+
return ok
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Валідує meta.json одного скіла.
|
|
45
|
+
* @param {string} id ідентифікатор скіла
|
|
46
|
+
* @param {string} skillDir каталог скіла
|
|
47
|
+
* @param {ReturnType<typeof createViolationReporter>} reporter репортер
|
|
48
|
+
* @returns {void}
|
|
49
|
+
*/
|
|
50
|
+
function checkSkill(id, skillDir, reporter) {
|
|
51
|
+
let skillOk = true
|
|
52
|
+
|
|
53
|
+
if (existsSync(join(skillDir, 'auto.md'))) {
|
|
54
|
+
reporter.fail(`skills/${id}: залишковий auto.md — видали (метадані тепер у main.json)`)
|
|
55
|
+
skillOk = false
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const raw = readSkillMetaRaw(skillDir)
|
|
59
|
+
if (!raw) {
|
|
60
|
+
reporter.fail(`skills/${id}: відсутній або невалідний main.json (очікується {"auto"?, "worktree": bool})`)
|
|
61
|
+
return
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
if (!checkSkillFields(id, raw, reporter)) skillOk = false
|
|
65
|
+
|
|
66
|
+
if (skillOk) {
|
|
67
|
+
reporter.pass(`skills/${id}: main.json валідний`)
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Валідує всі `npm/skills/<id>/meta.json`.
|
|
73
|
+
* @param {import('@7n/rules/scripts/lib/lint-surface/types.mjs').LintContext} ctx контекст лінту.
|
|
74
|
+
* @returns {Promise<import('@7n/rules/scripts/lib/lint-surface/types.mjs').LintResult>} результат перевірки з порушеннями.
|
|
75
|
+
*/
|
|
76
|
+
export function lint(ctx) {
|
|
77
|
+
const cwd = ctx.cwd
|
|
78
|
+
const reporter = createViolationReporter(ctx)
|
|
79
|
+
const skillsDir = join(cwd, 'npm', 'skills')
|
|
80
|
+
if (!existsSync(skillsDir)) {
|
|
81
|
+
reporter.pass('npm/skills/ відсутній — немає скілів для валідації')
|
|
82
|
+
return Promise.resolve(reporter.result())
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
for (const entry of readdirSync(skillsDir, { withFileTypes: true })) {
|
|
86
|
+
if (!entry.isDirectory() || entry.name.startsWith('.')) continue
|
|
87
|
+
checkSkill(entry.name, join(skillsDir, entry.name), reporter)
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
return Promise.resolve(reporter.result())
|
|
91
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
## Валідація `main.json` скілів
|
|
2
|
+
|
|
3
|
+
Кожен скіл у `npm/skills/<id>/` повинен мати коректний `main.json` (метадані скіла).
|
|
4
|
+
|
|
5
|
+
Перевірки (`skill_meta.mjs`):
|
|
6
|
+
|
|
7
|
+
- **`auto.md` є пережитком** — якщо такий файл залишився, `check` вимагає його видалити (метадані тепер у `main.json`).
|
|
8
|
+
- **`main.json` має бути валідним JSON** із коректними полями:
|
|
9
|
+
- **`worktree`** (обовʼязкове): `boolean`. Якщо `true` — скіл запускається виключно в окремому git-worktree.
|
|
10
|
+
- **`auto`** (опційне): `"завжди"` або непорожній масив ідентифікаторів правил-тригерів.
|
|
11
|
+
- **`requireRoot`** (опційне): `boolean`. Значення `false` несумісне з `worktree: true` — таку комбінацію `check` відхиляє.
|