@nitra/cursor 12.8.6 → 12.8.8
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 +1 -1
- package/rules/abie/main.mdc +9 -5
- package/rules/abie/policy/base_deployment_preem/base_deployment_preem.mdc +22 -0
- package/rules/abie/policy/clean_merged_ignore_branches/clean_merged_ignore_branches.mdc +19 -0
- package/rules/abie/policy/health_check_policy/health_check_policy.mdc +17 -0
- package/rules/abie/policy/http_route_base/http_route_base.mdc +9 -0
- package/rules/abie/policy/package_json_shared/package_json_shared.mdc +17 -0
- package/rules/adr/js/hooks.mdc +32 -0
- package/rules/adr/js/madr_format.mdc +96 -0
- package/rules/adr/js/settings_policy.mdc +34 -0
- package/rules/adr/main.mdc +17 -95
- package/rules/adr/policy/settings_json/settings_json.mdc +7 -0
- package/rules/adr/policy/settings_local_json/settings_local_json.mdc +7 -0
- package/rules/bun/js/bunfig.mdc +12 -0
- package/rules/bun/js/layout.mdc +60 -0
- package/rules/bun/js/lint.mdc +9 -0
- package/rules/bun/js/package_json.mdc +19 -0
- package/rules/bun/main.mdc +7 -60
- package/rules/bun/policy/bunfig/bunfig.mdc +12 -0
- package/rules/bun/policy/package_json/package_json.mdc +14 -0
- package/rules/capacitor/js/ios_spm.mdc +69 -0
- package/rules/capacitor/js/version.mdc +29 -0
- package/rules/capacitor/main.mdc +6 -22
- package/rules/capacitor/policy/package_json/package_json.mdc +9 -0
- package/rules/changelog/js/agent-workflow.mdc +15 -0
- package/rules/changelog/js/changelog-format.mdc +33 -0
- package/rules/changelog/js/comparison-models.mdc +40 -0
- package/rules/changelog/main.mdc +4 -98
- package/rules/ci4/js/marksman_config.mdc +31 -0
- package/rules/ci4/js/vscode_extensions.mdc +33 -0
- package/rules/ci4/main.mdc +16 -14
- package/rules/ci4/policy/vscode_extensions/vscode_extensions.mdc +9 -0
- package/rules/docker/js/compile.mdc +44 -0
- package/rules/docker/js/hadolint.mdc +50 -0
- package/rules/docker/js/mirror.mdc +13 -0
- package/rules/docker/js/multistage.mdc +13 -0
- package/rules/docker/js/native-addon.mdc +43 -0
- package/rules/docker/js/nginx-tag.mdc +7 -0
- package/rules/docker/js/nginx-user.mdc +37 -0
- package/rules/docker/js/non-root.mdc +39 -0
- package/rules/docker/main.mdc +13 -196
- package/rules/docker/policy/lint_docker_yml/lint_docker_yml.mdc +14 -0
- package/rules/efes/main.mdc +1 -1
- package/rules/efes/policy/package_json_shared/package_json_shared.mdc +30 -0
- package/rules/ga/js/lint_toolchain.mdc +15 -0
- package/rules/ga/js/required_workflows.mdc +35 -0
- package/rules/ga/js/vscode.mdc +17 -0
- package/rules/ga/js/workflow_common.mdc +108 -0
- package/rules/ga/js/workflows.mdc +32 -0
- package/rules/ga/js/zizmor.mdc +7 -0
- package/rules/ga/main.mdc +16 -119
- package/rules/ga/policy/clean_ga_workflows/clean_ga_workflows.mdc +18 -0
- package/rules/ga/policy/clean_merged_branch/clean_merged_branch.mdc +22 -0
- package/rules/ga/policy/git_ai/git_ai.mdc +19 -0
- package/rules/ga/policy/lint_ga/lint_ga.mdc +21 -0
- package/rules/ga/policy/vscode_extensions/vscode_extensions.mdc +9 -0
- package/rules/ga/policy/vscode_settings/vscode_settings.mdc +9 -0
- package/rules/ga/policy/workflow_common/workflow_common.mdc +18 -0
- package/rules/ga/policy/zizmor_yml/zizmor_yml.mdc +9 -0
- package/rules/graphql/js/tooling.mdc +13 -0
- package/rules/graphql/js/vscode_extensions.mdc +13 -0
- package/rules/graphql/main.mdc +4 -21
- package/rules/graphql/policy/vscode_extensions/vscode_extensions.mdc +9 -0
- package/rules/hasura/js/internal_urls.mdc +27 -0
- package/rules/hasura/js/migrations.mdc +13 -0
- package/rules/hasura/js/svc_hl.mdc +17 -0
- package/rules/hasura/main.mdc +6 -30
- package/rules/hasura/policy/svc_hl/svc_hl.mdc +15 -0
- package/rules/image-avif/js/avif_generation.mdc +26 -0
- package/rules/image-avif/js/package_json_optout.mdc +21 -0
- package/rules/image-avif/main.mdc +5 -34
- package/rules/image-avif/policy/package_json/package_json.mdc +18 -0
- package/rules/image-compress/js/package_json.mdc +7 -0
- package/rules/image-compress/js/package_setup.mdc +13 -0
- package/rules/image-compress/main.mdc +4 -12
- package/rules/image-compress/policy/package_json/package_json.mdc +13 -0
- package/rules/js/docs/index.md +3 -3
- package/rules/js/js/dep-policy.mdc +17 -0
- package/rules/js/js/eslint-config.mdc +28 -0
- package/rules/js/js/extensions.mdc +8 -0
- package/rules/js/js/file-extensions.mdc +12 -0
- package/rules/js/js/for-in.mdc +26 -0
- package/rules/js/js/jscpd.mdc +42 -0
- package/rules/js/js/knip.mdc +15 -0
- package/rules/js/js/lint-js-workflow.mdc +58 -0
- package/rules/js/js/oxlintrc.mdc +20 -0
- package/rules/js/js/package-json.mdc +31 -0
- package/rules/js/js/tests.mdc +9 -0
- package/rules/js/js/utils-lib-structure.mdc +15 -0
- package/rules/js/main.mdc +19 -211
- package/rules/js/policy/jscpd/jscpd.mdc +14 -0
- package/rules/js/policy/lint_js_yml/lint_js_yml.mdc +14 -0
- package/rules/js/policy/package_json/package_json.mdc +15 -0
- package/rules/js/policy/vscode_extensions/vscode_extensions.mdc +11 -0
- package/rules/js-bun-db/js/bun-sql-migration.mdc +15 -0
- package/rules/js-bun-db/js/connection.mdc +42 -0
- package/rules/js-bun-db/js/pg-format-identifiers.mdc +102 -0
- package/rules/js-bun-db/js/pg-format-shim.mdc +99 -0
- package/rules/js-bun-db/js/pg-leftover.mdc +27 -0
- package/rules/js-bun-db/js/pg-listen-notify.mdc +51 -0
- package/rules/js-bun-db/js/query-safety.mdc +117 -0
- package/rules/js-bun-db/js/sql-array.mdc +88 -0
- package/rules/js-bun-db/js/unsafe.mdc +65 -0
- package/rules/js-bun-db/main.mdc +12 -607
- package/rules/js-bun-db/policy/package_json/package_json.mdc +17 -0
- package/rules/js-bun-redis/js/imports.mdc +47 -0
- package/rules/js-bun-redis/js/package_json.mdc +44 -0
- package/rules/js-bun-redis/main.mdc +4 -10
- package/rules/js-bun-redis/policy/package_json/package_json.mdc +11 -0
- package/rules/js-mssql/js/mssql-in-list.mdc +38 -0
- package/rules/js-mssql/js/mssql-pool.mdc +56 -0
- package/rules/js-mssql/js/mssql-query-template.mdc +33 -0
- package/rules/js-mssql/js/mssql-tvp.mdc +75 -0
- package/rules/js-mssql/js/mssql-version.mdc +7 -0
- package/rules/js-mssql/main.mdc +10 -198
- package/rules/js-mssql/policy/package_json/package_json.mdc +9 -0
- package/rules/js-run/js/check-env.mdc +35 -0
- package/rules/js-run/js/conn-aliases.mdc +109 -0
- package/rules/js-run/js/jsconfig.mdc +20 -0
- package/rules/js-run/js/otel-configmap.mdc +6 -0
- package/rules/js-run/js/pino.mdc +6 -0
- package/rules/js-run/js/project-structure.mdc +11 -0
- package/rules/js-run/js/runtime.mdc +14 -0
- package/rules/js-run/js/scope.mdc +11 -0
- package/rules/js-run/js/settimeout.mdc +11 -0
- package/rules/js-run/js/temporal.mdc +5 -0
- package/rules/js-run/main.mdc +16 -216
- package/rules/js-run/policy/configmap/configmap.mdc +31 -0
- package/rules/js-run/policy/jsconfig/jsconfig.mdc +25 -0
- package/rules/js-run/policy/package_json/package_json.mdc +38 -0
- package/rules/k8s/js/configmap.mdc +41 -0
- package/rules/k8s/js/deployment_resources.mdc +49 -0
- package/rules/k8s/js/hasura_httproute.mdc +91 -0
- package/rules/k8s/js/hpa_apiversion.mdc +27 -0
- package/rules/k8s/js/ingress_gateway.mdc +16 -0
- package/rules/k8s/js/kustomize_structure.mdc +144 -0
- package/rules/k8s/js/lint_k8s.mdc +72 -0
- package/rules/k8s/js/multidoc_yaml.mdc +5 -0
- package/rules/k8s/js/network_policy.mdc +136 -0
- package/rules/k8s/js/schema_modeline.mdc +57 -0
- package/rules/k8s/js/service.mdc +44 -0
- package/rules/k8s/js/topology_hpa_pdb.mdc +181 -0
- package/rules/k8s/main.mdc +29 -834
- package/rules/k8s/policy/base_kustomization/base_kustomization.mdc +12 -0
- package/rules/k8s/policy/base_manifest/base_manifest.mdc +14 -0
- package/rules/k8s/policy/gateway/gateway.mdc +17 -0
- package/rules/k8s/policy/hasura_configmap/hasura_configmap.mdc +20 -0
- package/rules/k8s/policy/hasura_httproute/hasura_httproute.mdc +16 -0
- package/rules/k8s/policy/hpa_pdb/hpa_pdb.mdc +23 -0
- package/rules/k8s/policy/kustomization/kustomization.mdc +20 -0
- package/rules/k8s/policy/manifest/manifest.mdc +17 -0
- package/rules/k8s/policy/network_policy/network_policy.mdc +22 -0
- package/rules/k8s/policy/svc_hl_yaml/svc_hl_yaml.mdc +13 -0
- package/rules/k8s/policy/svc_yaml/svc_yaml.mdc +12 -0
- package/rules/nginx-default-tpl/js/dockerfile.mdc +36 -0
- package/rules/nginx-default-tpl/js/http-route.mdc +41 -0
- package/rules/nginx-default-tpl/js/ini-keys.mdc +21 -0
- package/rules/nginx-default-tpl/js/template-structure.mdc +86 -0
- package/rules/nginx-default-tpl/js/vscode.mdc +37 -0
- package/rules/nginx-default-tpl/main.mdc +8 -110
- package/rules/nginx-default-tpl/policy/vscode_extensions/vscode_extensions.mdc +11 -0
- package/rules/nginx-default-tpl/policy/vscode_settings/vscode_settings.mdc +15 -0
- package/rules/npm-module/js/docs/index.md +5 -5
- package/rules/npm-module/js/docs/rule_meta.md +6 -6
- package/rules/npm-module/js/docs/skill_meta.md +8 -8
- package/rules/npm-module/js/header_doc_pointer.mdc +18 -0
- package/rules/npm-module/js/package_structure.mdc +62 -0
- package/rules/npm-module/js/rule_meta.mdc +11 -0
- package/rules/npm-module/js/skill_meta.mdc +11 -0
- package/rules/npm-module/main.mdc +10 -52
- package/rules/npm-module/policy/emit_types_config/emit_types_config.mdc +40 -0
- package/rules/npm-module/policy/npm_package_json/npm_package_json.mdc +50 -0
- package/rules/npm-module/policy/root_package_json/root_package_json.mdc +37 -0
- package/rules/php/js/lint_php_yml.mdc +12 -0
- package/rules/php/js/tooling.mdc +66 -0
- package/rules/php/main.mdc +5 -66
- package/rules/php/policy/lint_php_yml/lint_php_yml.mdc +21 -0
- package/rules/python/js/lint_python_yml.mdc +23 -0
- package/rules/python/js/pyproject_toml.mdc +32 -0
- package/rules/python/js/tooling.mdc +23 -0
- package/rules/python/main.mdc +7 -32
- package/rules/python/policy/lint_python_yml/lint_python_yml.mdc +12 -0
- package/rules/python/policy/pyproject_toml/pyproject_toml.mdc +13 -0
- package/rules/rego/js/rego-lint.mdc +31 -0
- package/rules/rego/js/vscode_extensions.mdc +11 -0
- package/rules/rego/js/vscode_settings.mdc +13 -0
- package/rules/rego/main.mdc +10 -22
- package/rules/rego/policy/vscode_extensions/vscode_extensions.mdc +11 -0
- package/rules/rego/policy/vscode_settings/vscode_settings.mdc +19 -0
- package/rules/rust/js/coverage.mdc +28 -0
- package/rules/rust/js/lint.mdc +22 -0
- package/rules/rust/js/tauri_composition.mdc +8 -0
- package/rules/rust/js/vscode_extensions.mdc +12 -0
- package/rules/rust/main.mdc +8 -38
- package/rules/rust/policy/lint_rust_yml/lint_rust_yml.mdc +12 -0
- package/rules/rust/policy/vscode_extensions/vscode_extensions.mdc +9 -0
- package/rules/security/js/rego_policies.mdc +15 -0
- package/rules/security/js/sample_secret.mdc +19 -0
- package/rules/security/js/trufflehog.mdc +21 -0
- package/rules/security/main.mdc +7 -34
- package/rules/security/policy/lint_security_yml/lint_security_yml.mdc +7 -0
- package/rules/security/policy/package_json/package_json.mdc +7 -0
- package/rules/style/js/admin-table.mdc +88 -0
- package/rules/style/js/colors.mdc +21 -0
- package/rules/style/js/gap.mdc +22 -0
- package/rules/style/js/quasar-fixes.mdc +32 -0
- package/rules/style/js/quasar.mdc +7 -0
- package/rules/style/js/tooling.mdc +85 -0
- package/rules/style/main.mdc +12 -251
- package/rules/style/policy/lint_style_yml/lint_style_yml.mdc +13 -0
- package/rules/style/policy/package_json/package_json.mdc +18 -0
- package/rules/style/policy/vscode_extensions/vscode_extensions.mdc +13 -0
- package/rules/style/policy/vscode_settings/vscode_settings.mdc +19 -0
- package/rules/tauri/js/cargo_mutants_config.mdc +39 -0
- package/rules/tauri/js/tool_surface.mdc +21 -0
- package/rules/tauri/js/tooling.mdc +25 -0
- package/rules/tauri/main.mdc +6 -78
- package/rules/tauri/policy/vscode_extensions/vscode_extensions.mdc +21 -0
- package/rules/test/js/cargo_mutants_config.mdc +18 -0
- package/rules/test/js/docs/index.md +7 -7
- package/rules/test/js/location.mdc +52 -0
- package/rules/test/js/no-console-store-restore.mdc +11 -0
- package/rules/test/js/no-process-chdir.mdc +15 -0
- package/rules/test/js/no-relative-fs-path.mdc +22 -0
- package/rules/test/js/sandbox-aware-test.mdc +28 -0
- package/rules/test/js/stryker_config.mdc +26 -0
- package/rules/test/js/vitest-config-pool-forks.mdc +33 -0
- package/rules/test/main.mdc +16 -184
- package/rules/test/policy/package_json/package_json.mdc +16 -0
- package/rules/text/js/ci-lint-text.mdc +15 -0
- package/rules/text/js/cspell.mdc +81 -0
- package/rules/text/js/dotenv-linter.mdc +16 -0
- package/rules/text/js/forbidden-prettier.mdc +13 -0
- package/rules/text/js/markdownlint.mdc +25 -0
- package/rules/text/js/oxfmt.mdc +35 -0
- package/rules/text/js/package-json.mdc +26 -0
- package/rules/text/js/shellcheck.mdc +18 -0
- package/rules/text/js/v8r.mdc +23 -0
- package/rules/text/js/vscode.mdc +86 -0
- package/rules/text/main.mdc +20 -231
- package/rules/text/policy/cspell/cspell.mdc +34 -0
- package/rules/text/policy/lint_text/lint_text.mdc +19 -0
- package/rules/text/policy/markdownlint/markdownlint.mdc +38 -0
- package/rules/text/policy/oxfmtrc/oxfmtrc.mdc +11 -0
- package/rules/text/policy/package_json/package_json.mdc +33 -0
- package/rules/text/policy/vscode_extensions/vscode_extensions.mdc +13 -0
- package/rules/text/policy/vscode_settings/vscode_settings.mdc +13 -0
- package/rules/vue/js/composition-api.mdc +82 -0
- package/rules/vue/js/nheader-layout.mdc +171 -0
- package/rules/vue/js/node-imports.mdc +25 -0
- package/rules/vue/js/quasar-ui.mdc +32 -0
- package/rules/vue/js/structure.mdc +101 -0
- package/rules/vue/js/testing.mdc +32 -0
- package/rules/vue/js/tfm-translations.mdc +26 -0
- package/rules/vue/js/vite-config.mdc +126 -0
- package/rules/vue/js/vite-env.mdc +55 -0
- package/rules/vue/js/vue-imports.mdc +25 -0
- package/rules/vue/main.mdc +15 -641
- package/rules/vue/policy/package_json/package_json.mdc +30 -0
- package/scripts/docs/index.md +16 -16
- package/scripts/lib/docs/index.md +36 -36
- package/scripts/utils/docs/index.md +14 -14
|
@@ -17,14 +17,14 @@ docgen:
|
|
|
17
17
|
1. Перевіряє наявність каталогу `npm/skills` у поточному робочому каталозі. Якщо каталог відсутній, операція завершується успішно.
|
|
18
18
|
2. Ітерує по всіх підкаталогах у `npm/skills`.
|
|
19
19
|
3. Для кожного підкаталогу виконується перевірка метаданих скіла:
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
20
|
+
а. Перевіряється наявність файлу `auto.md` у каталозі скіла. Якщо він присутній, це вважається порушенням.
|
|
21
|
+
б. Зчитується вміст `main.json` скіла. Якщо файл відсутній або невалідний, перевірка для цього скіла припиняється.
|
|
22
|
+
в. Виконується перевірка полів `main.json` скіла:
|
|
23
|
+
i. `worktree` має бути булевим значенням.
|
|
24
|
+
ii. Якщо поле `auto` визначене, його вміст має бути розпізнаним як "завжди" або непорожній масив правил.
|
|
25
|
+
iii. `requireRoot` має бути булевим значенням, якщо визначений.
|
|
26
|
+
iv. Якщо `worktree` встановлено як `true`, а `requireRoot` як `false`, це вважається порушенням.
|
|
27
|
+
г. Якщо всі поля `main.json` валідні, це вважається успішним результатом для скіла.
|
|
28
28
|
4. Після перевірки всіх скілів повертається код виходу, що відображає загальний статус (0 — успіх, 1 — порушення).
|
|
29
29
|
|
|
30
30
|
## Публічний API
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
## Module-level JSDoc як pointer
|
|
2
|
+
|
|
3
|
+
Якщо поряд із `js/<stem>.mjs` є файл `js/docs/<stem>.md` — module-level JSDoc у `.mjs` має бути **pointer** (не більше одного непорожнього рядка), а не повноцінний наратив.
|
|
4
|
+
|
|
5
|
+
Логіка перевірки (`header_doc_pointer.mjs`):
|
|
6
|
+
|
|
7
|
+
- Сканується перший JSDoc-блок (`/** … */`) до першого `import`/`export` у файлі.
|
|
8
|
+
- Підраховуються непорожні рядки тіла (після зрізання `*`-відступу).
|
|
9
|
+
- Якщо їх більше одного — `check` падає з повідомленням про те, що `docs/<stem>.md` вже описує поведінку і module-level JSDoc має залишатись коротким.
|
|
10
|
+
|
|
11
|
+
**Покриття:** `npm/rules/*/js/*.mjs` і `npm/skills/*/js/*.mjs` (не тестові файли `*.test.mjs`). Якщо `docs/<stem>.md` відсутня — обмежень на довжину JSDoc немає.
|
|
12
|
+
|
|
13
|
+
**Приклад правильного pointer-JSDoc:**
|
|
14
|
+
|
|
15
|
+
```js
|
|
16
|
+
/** @see ./docs/package_structure.md */
|
|
17
|
+
import { existsSync } from 'node:fs'
|
|
18
|
+
```
|
|
@@ -0,0 +1,62 @@
|
|
|
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"` явно (як у самому `@nitra/cursor`).
|
|
9
|
+
- **Лише runtime-залежності у `npm/package.json`.** `devDependencies` тримай у **кореневому** `package.json` монорепо — тоді `npm install @nitra/<pkg>` не тягне інструментарій, потрібний лише для розробки самого пакета.
|
|
10
|
+
|
|
11
|
+
Перевірки JS (`package_structure.mjs`):
|
|
12
|
+
- Наявність `package.json`, `npm/`, `npm/package.json`.
|
|
13
|
+
- Walk шляхів з `"files"` з застосуванням негативних patterns і скан залишку на тест-патерни (walking + AST). Якщо після застосування негативних patterns у tarball лишається test-style файл — `check` падає з вказівкою, який саме негативний glob треба додати у `"files"`.
|
|
14
|
+
|
|
15
|
+
## TypeScript declaration (`npm/types`)
|
|
16
|
+
|
|
17
|
+
Файл **`npm/package.json`** має містити **`"types"`** (шлях до головного `.d.ts` або `.d.mts` під **`./types/…`**) і запис **`"types"`** у **`files`**, щоб npm публікував декларації.
|
|
18
|
+
|
|
19
|
+
Генерація — через **`tsc`** і **`bunx -p typescript`** (окремий пакет **`typescript`** у `devDependencies` не потрібен).
|
|
20
|
+
|
|
21
|
+
### Варіант A: є вихідний **`.js`** під **`npm/src/`**
|
|
22
|
+
|
|
23
|
+
Якщо під **`npm/src`** (рекурсивно) є хоча б один файл **`.js`**:
|
|
24
|
+
|
|
25
|
+
- **`"types": "./types/index.d.ts"`**;
|
|
26
|
+
- у **hk** на **`pre-commit`** з каталогу **`npm/`** викликай:
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
bunx -p typescript tsc src/**/*.js --declaration --allowJs --emitDeclarationOnly --outDir types --skipLibCheck
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Якщо glob не розгортається — **`bash -O globstar`** або **`include`** у **`tsconfig`** з тими самими **`compilerOptions`**.
|
|
33
|
+
|
|
34
|
+
### Варіант B: немає **`npm/src/**/*.js`** (наприклад лише **`bin/`**, **`scripts/**/*.mjs`**)
|
|
35
|
+
|
|
36
|
+
Не створюй штучний **`src/index.js`**. Замість цього:
|
|
37
|
+
|
|
38
|
+
1. Додай **`npm/tsconfig.emit-types.json`** з **`include`** на реальні шляхи (`.js` / `.mjs`), **`compilerOptions`**: **`allowJs`**, **`declaration`**, **`emitDeclarationOnly`**, **`outDir`: `"types"`**, **`skipLibCheck`**: **`true`** (за потреби **`rootDir`**, **`module`**, **`moduleResolution`**).
|
|
39
|
+
2. Після першого **`tsc`** подивись, який **`.d.ts`** / **`.d.mts`** відповідає публічному API, і вкажи його в **`types`** (наприклад **`./types/bin/cli.d.ts`**).
|
|
40
|
+
3. У **hk** на **`pre-commit`** з **`npm/`** викликай **`tsc -p tsconfig.emit-types.json`**. Якщо через імпорти **TypeScript** все одно згенерує зайві **`.d.mts`** у **`types/`**, після **`tsc`** обрізай дерево до потрібного entrypoint (наприклад залиш лише **`types/bin/n-cursor.d.ts`** через **`find`**), щоб у пакеті не збирались декларації внутрішніх модулів.
|
|
41
|
+
|
|
42
|
+
Файл **`tsconfig.emit-types.json`** тримай у репозиторії для **hk** / локальної генерації; у **`files`** його не додавай, якщо не хочеш публікувати його на **npm**.
|
|
43
|
+
|
|
44
|
+
## Git hooks: hk + pre-commit
|
|
45
|
+
|
|
46
|
+
У корені репозиторію — **`hk.pkl`** (або **`.config/hk.pkl`**) з **`["pre-commit"]`** і командою з відповідного варіанту (A або B) вище.
|
|
47
|
+
|
|
48
|
+
Після додавання **`hk.pkl`**: **`hk install`**.
|
|
49
|
+
|
|
50
|
+
## npm publish
|
|
51
|
+
|
|
52
|
+
**`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).
|
|
53
|
+
|
|
54
|
+
Workflow робить **release + publish** одним job (`release-publish`): крок **`Release (bump + CHANGELOG + tag)`** (`bunx n-cursor 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-cursor 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 й без міграторів.
|
|
55
|
+
|
|
56
|
+
- Канон: [npm-publish.yml.snippet.yml](./policy/npm_publish_yml/template/npm-publish.yml.snippet.yml)
|
|
57
|
+
|
|
58
|
+
## Канонічні конфіги
|
|
59
|
+
|
|
60
|
+
- Кореневий `package.json` (workspaces): [package.json.snippet.json](./policy/root_package_json/template/package.json.snippet.json)
|
|
61
|
+
- `npm/package.json` (whitelist `files` обовʼязково має містити `types`): [package.json.snippet.json](./policy/npm_package_json/template/package.json.snippet.json)
|
|
62
|
+
- `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,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`** (опційне): `"per-file"` або `"full"`. Якщо вказано — `main.mjs` повинен експортувати функцію `lint` (або `export { lint } from …`).
|
|
@@ -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` відхиляє.
|
|
@@ -7,53 +7,13 @@ version: '1.14'
|
|
|
7
7
|
|
|
8
8
|
Bun monorepo: workspace **`npm/`**, кореневий **`package.json`**, **`.github/workflows/`**; опційно **`demo/`**.
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
[npm-module-package_structure](./js/package_structure.mdc)
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
[npm-module-rule_meta](./js/rule_meta.mdc)
|
|
13
13
|
|
|
14
|
-
-
|
|
15
|
-
- **Тести й фікстури не публікуються — через негативні 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"` явно (як у самому `@nitra/cursor`).
|
|
16
|
-
- **Лише runtime-залежності у `npm/package.json`.** `devDependencies` тримай у **кореневому** `package.json` монорепо — тоді `npm install @nitra/<pkg>` не тягне інструментарій, потрібний лише для розробки самого пакета.
|
|
14
|
+
[npm-module-skill_meta](./js/skill_meta.mdc)
|
|
17
15
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
- Пер-документні правила для `npm/package.json` (whitelist `files`, заборона `devDependencies`, форма `types`) — у rego-пакеті `npm_module.npm_package_json` (`npm/policy/npm_module/npm_package_json/`).
|
|
21
|
-
- Walk шляхів з `"files"` з застосуванням негативних patterns і скан залишку на тест-патерни (walking + AST JS/TS) — у `check.mjs::checkNoTestsInPublishedFiles` (FS / AST не лягають у rego). Якщо після застосування негативних patterns у tarball лишається test-style файл — `check` падає з вказівкою, який саме негативний glob треба додати у `"files"`.
|
|
22
|
-
|
|
23
|
-
## TypeScript declaration (`npm/types`)
|
|
24
|
-
|
|
25
|
-
Файл **`npm/package.json`** має містити **`"types"`** (шлях до головного `.d.ts` або `.d.mts` під **`./types/…`**) і запис **`"types"`** у **`files`**, щоб npm публікував декларації.
|
|
26
|
-
|
|
27
|
-
Генерація — через **`tsc`** і **`bunx -p typescript`** (окремий пакет **`typescript`** у `devDependencies` не потрібен).
|
|
28
|
-
|
|
29
|
-
### Варіант A: є вихідний **`.js`** під **`npm/src/`**
|
|
30
|
-
|
|
31
|
-
Якщо під **`npm/src`** (рекурсивно) є хоча б один файл **`.js`**:
|
|
32
|
-
|
|
33
|
-
- **`"types": "./types/index.d.ts"`**;
|
|
34
|
-
- у **hk** на **`pre-commit`** з каталогу **`npm/`** викликай:
|
|
35
|
-
|
|
36
|
-
```bash
|
|
37
|
-
bunx -p typescript tsc src/**/*.js --declaration --allowJs --emitDeclarationOnly --outDir types --skipLibCheck
|
|
38
|
-
```
|
|
39
|
-
|
|
40
|
-
Якщо glob не розгортається — **`bash -O globstar`** або **`include`** у **`tsconfig`** з тими самими **`compilerOptions`**.
|
|
41
|
-
|
|
42
|
-
### Варіант B: немає **`npm/src/**/*.js`** (наприклад лише **`bin/`**, **`scripts/**/*.mjs`**)
|
|
43
|
-
|
|
44
|
-
Не створюй штучний **`src/index.js`**. Замість цього:
|
|
45
|
-
|
|
46
|
-
1. Додай **`npm/tsconfig.emit-types.json`** з **`include`** на реальні шляхи (`.js` / `.mjs`), **`compilerOptions`**: **`allowJs`**, **`declaration`**, **`emitDeclarationOnly`**, **`outDir`: `"types"`**, **`skipLibCheck`**: **`true`** (за потреби **`rootDir`**, **`module`**, **`moduleResolution`**).
|
|
47
|
-
2. Після першого **`tsc`** подивись, який **`.d.ts`** / **`.d.mts`** відповідає публічному API, і вкажи його в **`types`** (наприклад **`./types/bin/cli.d.ts`**).
|
|
48
|
-
3. У **hk** на **`pre-commit`** з **`npm/`** викликай **`tsc -p tsconfig.emit-types.json`**. Якщо через імпорти **TypeScript** все одно згенерує зайві **`.d.mts`** у **`types/`**, після **`tsc`** обрізай дерево до потрібного entrypoint (наприклад залиш лише **`types/bin/n-cursor.d.ts`** через **`find`**), щоб у пакеті не збирались декларації внутрішніх модулів.
|
|
49
|
-
|
|
50
|
-
Файл **`tsconfig.emit-types.json`** тримай у репозиторії для **hk** / локальної генерації; у **`files`** його не додавай, якщо не хочеш публікувати його на **npm**.
|
|
51
|
-
|
|
52
|
-
## Git hooks: hk + pre-commit
|
|
53
|
-
|
|
54
|
-
У корені репозиторію — **`hk.pkl`** (або **`.config/hk.pkl`**) з **`["pre-commit"]`** і командою з відповідного варіанту (A або B) вище.
|
|
55
|
-
|
|
56
|
-
Після додавання **`hk.pkl`**: **`hk install`**.
|
|
16
|
+
[npm-module-header_doc_pointer](./js/header_doc_pointer.mdc)
|
|
57
17
|
|
|
58
18
|
## Версія та CHANGELOG
|
|
59
19
|
|
|
@@ -61,16 +21,14 @@ bunx -p typescript tsc src/**/*.js --declaration --allowJs --emitDeclarationOnly
|
|
|
61
21
|
|
|
62
22
|
Повна модель (база порівняння, інверсія шляхів, формат CHANGELOG, post-release-інваріант «верхня секція CHANGELOG == `version`») — у **`n-changelog.mdc`** (джерело істини). Це правило їй підпорядковане й власних інструкцій bump/CHANGELOG не дублює.
|
|
63
23
|
|
|
64
|
-
##
|
|
24
|
+
## Швидкий gate через conftest
|
|
65
25
|
|
|
66
|
-
|
|
26
|
+
Rego-пакети (запускаються через `npx @nitra/cursor fix`):
|
|
67
27
|
|
|
68
|
-
|
|
28
|
+
[npm-module-npm_package_json](./policy/npm_package_json/npm_package_json.mdc)
|
|
69
29
|
|
|
70
|
-
|
|
30
|
+
[npm-module-root_package_json](./policy/root_package_json/root_package_json.mdc)
|
|
71
31
|
|
|
72
|
-
|
|
32
|
+
[npm-module-emit_types_config](./policy/emit_types_config/emit_types_config.mdc)
|
|
73
33
|
|
|
74
|
-
-
|
|
75
|
-
- `npm/package.json` (whitelist `files` обовʼязково має містити `types`): [package.json.snippet.json](./policy/npm_package_json/template/package.json.snippet.json)
|
|
76
|
-
- `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)
|
|
34
|
+
- `npm_module.npm_publish_yml` — template-driven перевірка `.github/workflows/npm-publish.yml` (deep-subset: усі обовʼязкові поля й кроки з канонічного сніпету).
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
## Rego-gate: конфігурація генерації типів `npm/tsconfig.emit-types.json`
|
|
2
|
+
|
|
3
|
+
Rego-пакет: `npm-module.emit_types_config`
|
|
4
|
+
|
|
5
|
+
Цільовий файл: `npm/tsconfig.emit-types.json`
|
|
6
|
+
|
|
7
|
+
### Що перевіряється
|
|
8
|
+
|
|
9
|
+
Leaf-by-leaf порівняння з канонічним сніпетом (через `--data`): кожне поле всередині `compilerOptions` має точно відповідати очікуваному значенню. Якщо секція `compilerOptions` відсутня або не є обʼєктом — окрема deny-помилка.
|
|
10
|
+
|
|
11
|
+
Канонічний сніпет: [tsconfig.emit-types.json.snippet.json](./template/tsconfig.emit-types.json.snippet.json)
|
|
12
|
+
|
|
13
|
+
### Допустимі відхилення
|
|
14
|
+
|
|
15
|
+
Додаткові поля у `compilerOptions` (наприклад `rootDir`, `baseUrl`) не спричиняють помилку — перевіряється лише наявність і коректність обовʼязкових ключів зі сніпету.
|
|
16
|
+
|
|
17
|
+
### Приклади
|
|
18
|
+
|
|
19
|
+
✓ Правильно:
|
|
20
|
+
```json
|
|
21
|
+
{
|
|
22
|
+
"compilerOptions": {
|
|
23
|
+
"allowJs": true,
|
|
24
|
+
"declaration": true,
|
|
25
|
+
"emitDeclarationOnly": true,
|
|
26
|
+
"outDir": "types",
|
|
27
|
+
"skipLibCheck": true
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
✗ Неправильно — неправильний `outDir`:
|
|
33
|
+
```json
|
|
34
|
+
{ "compilerOptions": { "outDir": "dist" } }
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
✗ Неправильно — відсутній `compilerOptions`:
|
|
38
|
+
```json
|
|
39
|
+
{}
|
|
40
|
+
```
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
## Rego-gate: валідація `npm/package.json`
|
|
2
|
+
|
|
3
|
+
Rego-пакет: `npm-module.npm_package_json`
|
|
4
|
+
|
|
5
|
+
Цільовий файл: `npm/package.json`
|
|
6
|
+
|
|
7
|
+
### Що перевіряється
|
|
8
|
+
|
|
9
|
+
**Поле `types`** (логіка в rego, не template-driven):
|
|
10
|
+
- Має відповідати патерну `./types/index.d.ts` або `./types/<назва>.d.ts|.d.mts`.
|
|
11
|
+
- Шляхи поза директорією `types/` або з іншими розширеннями (`.ts` без `.d`) — deny.
|
|
12
|
+
|
|
13
|
+
**Поле `files`** (частково template-driven):
|
|
14
|
+
- Обовʼязкове, має бути непорожнім масивом.
|
|
15
|
+
- Subset-of перевірка: кожне значення з канонічного сніпету має бути присутнє у `files`. За замовчуванням — `"types"` обовʼязковий.
|
|
16
|
+
|
|
17
|
+
**Поле `devDependencies`** (inverse-pattern, логіка в rego):
|
|
18
|
+
- Не публікуються користувачам пакета — має бути відсутнє або порожнє `{}`.
|
|
19
|
+
- Наявність будь-яких devDeps → deny з переліком залежностей. Перенести у кореневий `package.json`.
|
|
20
|
+
|
|
21
|
+
Канонічний сніпет `files`: [package.json.snippet.json](./template/package.json.snippet.json)
|
|
22
|
+
|
|
23
|
+
FS-перевірки (наявність файлу зі шляху `types`, скан tarball на тест-патерни) — у JS-перевірці, не тут.
|
|
24
|
+
|
|
25
|
+
### Приклади
|
|
26
|
+
|
|
27
|
+
✓ Правильно:
|
|
28
|
+
```json
|
|
29
|
+
{
|
|
30
|
+
"name": "@nitra/cursor",
|
|
31
|
+
"types": "./types/bin/n-cursor.d.ts",
|
|
32
|
+
"files": ["types", "mdc", "bin", "CHANGELOG.md"],
|
|
33
|
+
"dependencies": { "oxc-parser": "^0.128.0" }
|
|
34
|
+
}
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
✗ Неправильно — `types` поза директорією `types/`:
|
|
38
|
+
```json
|
|
39
|
+
{ "types": "./dist/index.d.ts" }
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
✗ Неправильно — `files` без `"types"`:
|
|
43
|
+
```json
|
|
44
|
+
{ "files": ["bin", "mdc"] }
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
✗ Неправильно — наявні `devDependencies`:
|
|
48
|
+
```json
|
|
49
|
+
{ "devDependencies": { "@nitra/cursor": "^1.0.0" } }
|
|
50
|
+
```
|
|
@@ -0,0 +1,37 @@
|
|
|
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
|
+
```json
|
|
21
|
+
{ "workspaces": ["npm"] }
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
✓ Правильно — `workspaces` містить `"npm"` разом з іншими:
|
|
25
|
+
```json
|
|
26
|
+
{ "workspaces": ["demo", "npm", "tests"] }
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
✗ Неправильно — `workspaces` відсутній:
|
|
30
|
+
```json
|
|
31
|
+
{ "name": "monorepo" }
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
✗ Неправильно — `workspaces` без `"npm"`:
|
|
35
|
+
```json
|
|
36
|
+
{ "workspaces": ["demo"] }
|
|
37
|
+
```
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
## CI: `.github/workflows/lint-php.yml`
|
|
2
|
+
|
|
3
|
+
Канон workflow — [lint-php.yml.snippet.yml](./policy/lint_php_yml/template/lint-php.yml.snippet.yml).
|
|
4
|
+
|
|
5
|
+
Файл запускається при push/PR до `dev`/`main` за змінами в `**/*.php`, `composer.json`, `composer.lock`, `phpstan.neon`, `phpstan.neon.dist`, `psalm.xml` або самого workflow.
|
|
6
|
+
|
|
7
|
+
Кроки job `php`:
|
|
8
|
+
1. `actions/checkout@v6` (без persist-credentials)
|
|
9
|
+
2. `./.github/actions/setup-bun-deps`
|
|
10
|
+
3. `shivammathur/setup-php@v2` — PHP 8.5
|
|
11
|
+
4. `composer install --no-interaction --no-progress --prefer-dist`
|
|
12
|
+
5. `n-cursor lint php --read-only`
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
## PHP-інструменти лінту
|
|
2
|
+
|
|
3
|
+
Весь код повинен відповідати PHP 8.5, перевірятися через PHPCompatibility і конвертуватися через Rector.
|
|
4
|
+
|
|
5
|
+
Код має бути добре задокументований через phpDoc:
|
|
6
|
+
|
|
7
|
+
```php
|
|
8
|
+
/** @param array<int, string> $items */
|
|
9
|
+
function process($items) {
|
|
10
|
+
foreach ($items as $id => $name) {
|
|
11
|
+
// PHPStan знає, що $id — int, $name — string
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
### PHP_CodeSniffer (phpcs) і пакет `squizlabs/php_codesniffer`
|
|
17
|
+
|
|
18
|
+
Стиль, базові ризики, за потреби окремі стандарти. Для **SQL injection**, **XSS**, **небезпечні функції** — PHPCS + **php-security-audit** (стандарт `Security`).
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
phpcs --standard=Security app/
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
### PHPStan
|
|
25
|
+
|
|
26
|
+
Статичний аналіз типів і смертельних слабких місць; **PHPStan Taint Analysis** (`phpstan/phpstan-taint-analysis`) — для потоку даних (taint) у стилі security-аналізу.
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
vendor/bin/phpstan analyse
|
|
30
|
+
# після підключення розширення taint — у phpstan.neon/ neon.dist
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
### PHP-CS-Fixer
|
|
34
|
+
|
|
35
|
+
Форматтер/фіксер коду; у **lint** зазвичай перевірка без змін (`--dry-run`).
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
vendor/bin/php-cs-fixer fix --dry-run --diff
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
### Psalm
|
|
42
|
+
|
|
43
|
+
Альтернативний/додатковий аналізатор; **Psalm Security Plugin** (`vimeo/psalm` + пакет на кшталт `psalm/plugin-security` залежно від вибраної збірки) — для security-орієнтованих правил.
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
vendor/bin/psalm
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### `composer audit`
|
|
50
|
+
|
|
51
|
+
Перевірка відомих вразливостей залежностей за даними **Packagist/security-advisories**.
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
composer audit
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## Запуск lint-php
|
|
58
|
+
|
|
59
|
+
`composer`-інструменти не мають єдиного CLI, який сам обходить репозиторій, тому php-лінт делегується у JS-скрипт-обгортку. Запуск — через **`n-cursor lint php`** (CI — `--read-only`); окремого `package.json`-скрипта немає.
|
|
60
|
+
|
|
61
|
+
Скрипт `run-php.mjs`:
|
|
62
|
+
|
|
63
|
+
- якщо `composer.json` у корені відсутній — вихід 0 (перевірка пропущена);
|
|
64
|
+
- якщо `composer.json` є, але `composer` не знайдено в PATH — це помилка;
|
|
65
|
+
- `composer audit` — обовʼязковий;
|
|
66
|
+
- `vendor/bin/php-cs-fixer`, `vendor/bin/phpcs`, `vendor/bin/phpstan`, `vendor/bin/psalm` — запускаються лише якщо встановлені (інакше крок пропускається з повідомленням).
|
package/rules/php/main.mdc
CHANGED
|
@@ -5,73 +5,12 @@ globs: "**/*.php"
|
|
|
5
5
|
alwaysApply: false
|
|
6
6
|
---
|
|
7
7
|
|
|
8
|
-
Весь код повинен відповідати PHP 8.5
|
|
8
|
+
Весь код повинен відповідати PHP 8.5 (PHPCompatibility + Rector). Лінт запускається через `n-cursor lint php`.
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
[php-tooling](./js/tooling.mdc)
|
|
11
11
|
|
|
12
|
-
|
|
13
|
-
/** @param array<int, string> $items */
|
|
14
|
-
function process($items) {
|
|
15
|
-
foreach ($items as $id => $name) {
|
|
16
|
-
// PHPStan знає, що $id — int, $name — string
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
```
|
|
12
|
+
[php-lint_php_yml](./js/lint_php_yml.mdc)
|
|
20
13
|
|
|
21
|
-
##
|
|
14
|
+
## Швидкий gate через conftest
|
|
22
15
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
Стиль, базові ризики, за потреби окремі стандарти. Для **SQL injection**, **XSS**, **небезпечні функції** — PHPCS + **php-security-audit** (стандарт `Security`).
|
|
26
|
-
|
|
27
|
-
```bash
|
|
28
|
-
phpcs --standard=Security app/
|
|
29
|
-
```
|
|
30
|
-
|
|
31
|
-
### PHPStan
|
|
32
|
-
|
|
33
|
-
Статичний аналіз типів і смертельних слабких місць; **PHPStan Taint Analysis** (`phpstan/phpstan-taint-analysis`) — для потоку даних (taint) у стилі security-аналізу.
|
|
34
|
-
|
|
35
|
-
```bash
|
|
36
|
-
vendor/bin/phpstan analyse
|
|
37
|
-
# після підключення розширення taint — у phpstan.neon/ neon.dist
|
|
38
|
-
```
|
|
39
|
-
|
|
40
|
-
### PHP-CS-Fixer
|
|
41
|
-
|
|
42
|
-
Форматтер/фіксер коду; у **lint** зазвичай перевірка без змін (`--dry-run`).
|
|
43
|
-
|
|
44
|
-
```bash
|
|
45
|
-
vendor/bin/php-cs-fixer fix --dry-run --diff
|
|
46
|
-
```
|
|
47
|
-
|
|
48
|
-
### Psalm
|
|
49
|
-
|
|
50
|
-
Альтернативний/додатковий аналізатор; **Psalm Security Plugin** (`vimeo/psalm` + пакет на кшталт `psalm/plugin-security` залежно від вибраної збірки) — для security-орієнтованих правил.
|
|
51
|
-
|
|
52
|
-
```bash
|
|
53
|
-
vendor/bin/psalm
|
|
54
|
-
```
|
|
55
|
-
|
|
56
|
-
### `composer audit`
|
|
57
|
-
|
|
58
|
-
Перевірка відомих вразливостей залежностей за даними **Packagist/security-advisories**.
|
|
59
|
-
|
|
60
|
-
```bash
|
|
61
|
-
composer audit
|
|
62
|
-
```
|
|
63
|
-
|
|
64
|
-
## lint-php
|
|
65
|
-
|
|
66
|
-
`composer`-інструмененти не мають єдиного CLI, який сам обходить репозиторій, тому php-лінт делегується у JS-скрипт-обгортку. Запуск — через **`n-cursor lint php`** (CI — `--read-only`); окремого `package.json`-скрипта немає.
|
|
67
|
-
|
|
68
|
-
Скрипт `run-php.mjs`:
|
|
69
|
-
|
|
70
|
-
- якщо `composer.json` у корені відсутній — вихід 0 (перевірка пропущена);
|
|
71
|
-
- якщо `composer.json` є, але `composer` не знайдено в PATH — це помилка;
|
|
72
|
-
- `composer audit` — обовʼязковий;
|
|
73
|
-
- `vendor/bin/php-cs-fixer`, `vendor/bin/phpcs`, `vendor/bin/phpstan`, `vendor/bin/psalm` — запускаються лише якщо встановлені (інакше крок пропускається з повідомленням).
|
|
74
|
-
|
|
75
|
-
## CI: `.github/workflows/lint-php.yml`
|
|
76
|
-
|
|
77
|
-
- Канон: [lint-php.yml.snippet.yml](./policy/lint_php_yml/template/lint-php.yml.snippet.yml)
|
|
16
|
+
[php-lint_php_yml](./policy/lint_php_yml/lint_php_yml.mdc)
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
## Структура `.github/workflows/lint-php.yml`
|
|
2
|
+
|
|
3
|
+
Rego-пакет: `php.lint_php_yml`
|
|
4
|
+
|
|
5
|
+
Цільовий файл: `.github/workflows/lint-php.yml` (парситься як YAML).
|
|
6
|
+
|
|
7
|
+
Перевіряє, що у workflow присутні всі канонічні `run:`-кроки з template-сніпету — крок `n-cursor lint php --read-only` має бути в одному зі steps jobs.
|
|
8
|
+
|
|
9
|
+
Канонічний template-сніпет: [lint-php.yml.snippet.yml](./template/lint-php.yml.snippet.yml)
|
|
10
|
+
|
|
11
|
+
**✓ Правильно** — job `php` містить крок:
|
|
12
|
+
```yaml
|
|
13
|
+
- name: Lint PHP
|
|
14
|
+
run: n-cursor lint php --read-only
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
**✗ Неправильно** — крок відсутній або містить інший run-рядок:
|
|
18
|
+
```yaml
|
|
19
|
+
- name: Lint PHP
|
|
20
|
+
run: echo something
|
|
21
|
+
```
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
## CI: `.github/workflows/lint-python.yml`
|
|
2
|
+
|
|
3
|
+
Канонічний workflow: [lint-python.yml.snippet.yml](./policy/lint_python_yml/template/lint-python.yml.snippet.yml)
|
|
4
|
+
|
|
5
|
+
Без кроків `poetry install` / `snok/install-poetry` — лише `astral-sh/setup-uv@v8.0.0` + `uv sync --frozen`.
|
|
6
|
+
|
|
7
|
+
Обовʼязкові кроки:
|
|
8
|
+
- `actions/checkout@v6` з `persist-credentials: false`;
|
|
9
|
+
- `./.github/actions/setup-bun-deps` — встановлення JS-залежностей (для `n-cursor lint`);
|
|
10
|
+
- `astral-sh/setup-uv@v8.0.0` — встановлення uv;
|
|
11
|
+
- `uv sync --frozen` — встановлення Python-залежностей строго з lock-файлу;
|
|
12
|
+
- `n-cursor lint python --read-only` — запуск lint (без auto-fix у CI).
|
|
13
|
+
|
|
14
|
+
`uv` / `ruff` / `mypy` **не** додаються в кореневі `devDependencies` споживача — це окремий toolchain, що ставиться через `astral-sh/setup-uv` у CI або локально.
|
|
15
|
+
|
|
16
|
+
## Rego: python.lint_python_yml
|
|
17
|
+
|
|
18
|
+
Polісі `policy/lint_python_yml/lint_python_yml.rego` — drift-safe перевірка через `--data template`:
|
|
19
|
+
|
|
20
|
+
- кожен `uses` з template має бути присутнім у workflow input;
|
|
21
|
+
- кожен `run` з template має бути substring серед run-кроків input.
|
|
22
|
+
|
|
23
|
+
Заборона Poetry-кроків (`snok/install-poetry`, `poetry install`) забезпечується відсутністю у каноні: правило вимагає uv-кроки, і жодних poetry-кроків у template немає.
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
## pyproject.toml: PEP 621 і заборона Poetry
|
|
2
|
+
|
|
3
|
+
Метадані проєкту — у секції **`[project]`** (PEP 621), а **не** в `[tool.poetry]`.
|
|
4
|
+
|
|
5
|
+
Обовʼязкові поля:
|
|
6
|
+
- `[project].name` — назва пакета;
|
|
7
|
+
- `[project].version` — статична версія;
|
|
8
|
+
- `[project].requires-python` — мінімальна версія Python;
|
|
9
|
+
- `[project].dependencies` — залежності (навіть порожній список).
|
|
10
|
+
|
|
11
|
+
Lock-файл — **`uv.lock`** (коммітиться). `poetry.lock` / `poetry.toml` мають бути відсутні.
|
|
12
|
+
|
|
13
|
+
Залежності: `uv add <pkg>`; dev-залежності: `uv add --dev <pkg>`.
|
|
14
|
+
|
|
15
|
+
Канонічний цільовий вигляд `pyproject.toml`: [pyproject.toml.snippet.toml](./policy/pyproject_toml/template/pyproject.toml.snippet.toml)
|
|
16
|
+
|
|
17
|
+
Заборонені під-таблиці `[tool.*]` (Poetry): [pyproject.toml.deny.toml](./policy/pyproject_toml/template/pyproject.toml.deny.toml)
|
|
18
|
+
|
|
19
|
+
## Міграція з Poetry на uv
|
|
20
|
+
|
|
21
|
+
1. Прибери `[tool.poetry]` і `poetry.lock` / `poetry.toml`.
|
|
22
|
+
2. Перенеси метадані в `[project]` (name, version, requires-python, dependencies) за PEP 621.
|
|
23
|
+
3. Згенеруй lock: `uv lock` → `uv.lock`.
|
|
24
|
+
4. Dev-залежності: `uv add --dev ruff mypy …`.
|
|
25
|
+
|
|
26
|
+
## Rego: python.pyproject_toml
|
|
27
|
+
|
|
28
|
+
Polисі `policy/pyproject_toml/pyproject_toml.rego` — дві групи правил:
|
|
29
|
+
|
|
30
|
+
**1. Заборона Poetry** — перевіряє, чи є заборонені під-таблиці `[tool.*]` з `pyproject.toml.deny.toml` (drift-safe через `--data template`).
|
|
31
|
+
|
|
32
|
+
**2. PEP 621** — `[project].name` і `[project].version` мають бути непорожніми рядками.
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
## Перевірка наявності uv-toolchain і відсутності Poetry
|
|
2
|
+
|
|
3
|
+
JS-перевірка (`js/tooling.mjs`) запускається, якщо в корені репо є `pyproject.toml`. Перевіряє:
|
|
4
|
+
|
|
5
|
+
- `uv.lock` — має існувати (зафіксувати командою `uv lock`);
|
|
6
|
+
- `poetry.lock` / `poetry.toml` — мають **бути відсутніми** (Poetry заборонено);
|
|
7
|
+
- `package.json` — має бути у корені (js-обгортка lint є частиною монорепо);
|
|
8
|
+
- `.github/workflows/lint-python.yml` — має існувати (структуру перевіряє Rego-полісі `python.lint_python_yml`).
|
|
9
|
+
|
|
10
|
+
Якщо `pyproject.toml` відсутній — перевірка пропускається з кодом 0 (проєкт не Python).
|
|
11
|
+
|
|
12
|
+
## lint-python: JS-скрипт-обгортка
|
|
13
|
+
|
|
14
|
+
Інструменти uv-екосистеми не мають єдиного CLI-обходу репо, тому python-лінт делегується у JS-скрипт-обгортку. Запуск — через **`n-cursor lint python`** (CI — `--read-only`); окремого `package.json`-скрипта немає.
|
|
15
|
+
|
|
16
|
+
Скрипт `rules/python/lint/lint.mjs`:
|
|
17
|
+
|
|
18
|
+
- якщо `pyproject.toml` у корені відсутній — вихід 0 (перевірка пропущена);
|
|
19
|
+
- якщо `pyproject.toml` є, але `uv` не знайдено в PATH — це помилка;
|
|
20
|
+
- `uv lock --check` і `uv sync --frozen` — обовʼязкові;
|
|
21
|
+
- `uv run ruff check --fix .` + `uv run ruff format .` — auto-fix (мутують робоче дерево, як `markdownlint-cli2 --fix` у lint-text);
|
|
22
|
+
- `uv run mypy .` — статична перевірка типів;
|
|
23
|
+
- усі `ruff`/`mypy`-кроки запускаються лише якщо інструмент доступний у середовищі (інакше крок пропускається з повідомленням).
|