@nitra/cursor 12.9.0 → 12.11.0

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.
Files changed (175) hide show
  1. package/.claude-template/settings.template.json +1 -23
  2. package/CHANGELOG.md +12 -0
  3. package/bin/n-cursor.js +8 -43
  4. package/docs/stryker.config.md +0 -2
  5. package/lib/docs/llm.md +16 -21
  6. package/lib/docs/omlx.md +20 -25
  7. package/lib/llm.mjs +25 -7
  8. package/lib/omlx.mjs +10 -3
  9. package/package.json +1 -1
  10. package/rules/abie/docs/main.md +0 -2
  11. package/rules/abie/lib/docs/http-route.md +0 -2
  12. package/rules/abie/main.mdc +0 -22
  13. package/rules/adr/docs/main.md +0 -2
  14. package/rules/adr/js/docs/hooks.md +16 -26
  15. package/rules/adr/js/hooks.mjs +59 -0
  16. package/rules/adr/main.mdc +0 -9
  17. package/rules/bun/docs/main.md +0 -2
  18. package/rules/bun/main.mdc +1 -15
  19. package/rules/capacitor/docs/main.md +0 -2
  20. package/rules/capacitor/main.mdc +0 -6
  21. package/rules/changelog/docs/main.md +0 -2
  22. package/rules/changelog/js/agent-workflow.mdc +1 -1
  23. package/rules/changelog/js/consistency.mjs +57 -3
  24. package/rules/changelog/js/docs/consistency.md +26 -24
  25. package/rules/changelog/js/docs/index.md +2 -2
  26. package/rules/changelog/main.mdc +0 -5
  27. package/rules/ci4/docs/main.md +0 -2
  28. package/rules/ci4/main.mdc +0 -5
  29. package/rules/doc-files/docs/main.md +0 -2
  30. package/rules/doc-files/js/docs/docgen-crc.md +0 -2
  31. package/rules/doc-files/js/docs/docgen-extract.md +0 -2
  32. package/rules/doc-files/js/docs/docgen-files-batch.md +0 -2
  33. package/rules/doc-files/js/docs/docgen-gen.md +0 -2
  34. package/rules/doc-files/js/docs/docgen-judge-measure.md +0 -2
  35. package/rules/doc-files/js/docs/docgen-judge.md +0 -2
  36. package/rules/doc-files/js/docs/docgen-scan.md +0 -2
  37. package/rules/doc-files/js/docs/run-lint.md +0 -2
  38. package/rules/docker/docs/main.md +0 -2
  39. package/rules/docker/js/docs/lint.md +0 -2
  40. package/rules/docker/lib/docs/docker-hadolint.md +0 -2
  41. package/rules/docker/main.mdc +1 -21
  42. package/rules/efes/docs/main.md +0 -2
  43. package/rules/efes/main.mdc +0 -1
  44. package/rules/feedback/docs/main.md +0 -2
  45. package/rules/ga/docs/main.md +0 -2
  46. package/rules/ga/js/docs/index.md +0 -1
  47. package/rules/ga/main.mdc +1 -31
  48. package/rules/graphql/docs/main.md +0 -2
  49. package/rules/graphql/main.mdc +0 -5
  50. package/rules/hasura/docs/main.md +0 -2
  51. package/rules/hasura/js/docs/index.md +3 -3
  52. package/rules/hasura/js/docs/migrations.md +0 -2
  53. package/rules/hasura/main.mdc +1 -11
  54. package/rules/image-avif/docs/main.md +0 -2
  55. package/rules/image-avif/main.mdc +1 -9
  56. package/rules/image-compress/docs/main.md +0 -2
  57. package/rules/image-compress/js/docs/index.md +0 -1
  58. package/rules/image-compress/main.mdc +1 -9
  59. package/rules/js/docs/main.md +0 -2
  60. package/rules/js/js/dep-policy.mjs +8 -4
  61. package/rules/js/js/docs/check.md +0 -2
  62. package/rules/js/js/docs/dep-policy.md +10 -12
  63. package/rules/js/js/docs/index.md +5 -5
  64. package/rules/js/js/docs/tooling.md +0 -2
  65. package/rules/js/js/docs/utils_imports.md +0 -2
  66. package/rules/js/main.mdc +0 -31
  67. package/rules/js-bun-db/docs/main.md +0 -2
  68. package/rules/js-bun-db/js/docs/safety.md +18 -23
  69. package/rules/js-bun-db/js/safety.mjs +31 -3
  70. package/rules/js-bun-db/lib/bun-sql-scan.mjs +123 -0
  71. package/rules/js-bun-db/lib/docs/bun-sql-scan.md +37 -331
  72. package/rules/js-bun-db/main.mdc +1 -23
  73. package/rules/js-bun-redis/docs/main.md +0 -2
  74. package/rules/js-bun-redis/main.mdc +0 -5
  75. package/rules/js-mssql/docs/main.md +0 -2
  76. package/rules/js-mssql/main.mdc +0 -12
  77. package/rules/js-run/docs/main.md +0 -2
  78. package/rules/js-run/js/docs/runtime.md +15 -13
  79. package/rules/js-run/js/runtime.mjs +48 -4
  80. package/rules/js-run/main.mdc +0 -25
  81. package/rules/k8s/docs/main.md +0 -2
  82. package/rules/k8s/main.mdc +0 -45
  83. package/rules/nginx-default-tpl/docs/main.md +0 -2
  84. package/rules/nginx-default-tpl/main.mdc +0 -13
  85. package/rules/npm-module/docs/main.md +0 -2
  86. package/rules/npm-module/js/docs/header_doc_pointer.md +0 -2
  87. package/rules/npm-module/js/docs/rule_meta.md +0 -2
  88. package/rules/npm-module/js/docs/skill_meta.md +0 -2
  89. package/rules/npm-module/main.mdc +1 -15
  90. package/rules/php/docs/main.md +0 -2
  91. package/rules/php/js/docs/index.md +0 -1
  92. package/rules/php/main.mdc +1 -9
  93. package/rules/python/docs/main.md +0 -2
  94. package/rules/python/js/docs/index.md +0 -1
  95. package/rules/python/main.mdc +1 -13
  96. package/rules/python/policy/lint_python_yml/lint_python_yml.rego +9 -0
  97. package/rules/python/policy/pyproject_toml/pyproject_toml.rego +15 -1
  98. package/rules/rego/docs/main.md +0 -2
  99. package/rules/rego/js/docs/index.md +2 -2
  100. package/rules/rego/js/docs/tooling.md +0 -2
  101. package/rules/rego/js/tooling.mdc +14 -0
  102. package/rules/rego/main.mdc +0 -9
  103. package/rules/rego/policy/package_json/package_json.mdc +12 -0
  104. package/rules/release/docs/main.md +0 -2
  105. package/rules/release/main.mdc +2 -2
  106. package/rules/rust/docs/main.md +0 -2
  107. package/rules/rust/js/docs/index.md +0 -1
  108. package/rules/rust/main.mdc +1 -11
  109. package/rules/rust/policy/package_json/package_json.mdc +12 -0
  110. package/rules/security/docs/main.md +0 -2
  111. package/rules/security/js/docs/index.md +0 -1
  112. package/rules/security/main.mdc +0 -13
  113. package/rules/style/docs/main.md +0 -2
  114. package/rules/style/js/docs/index.md +2 -2
  115. package/rules/style/js/docs/tooling.md +0 -2
  116. package/rules/style/main.mdc +1 -23
  117. package/rules/tauri/docs/main.md +0 -2
  118. package/rules/tauri/main.mdc +1 -11
  119. package/rules/test/docs/main.md +0 -2
  120. package/rules/test/js/docs/no-console-store-restore.md +0 -2
  121. package/rules/test/js/docs/sandbox-aware-test.md +0 -2
  122. package/rules/test/js/docs/stryker_config.md +0 -2
  123. package/rules/test/js/docs/vitest-config-pool-forks.md +0 -2
  124. package/rules/test/main.mdc +1 -21
  125. package/rules/text/docs/main.md +0 -2
  126. package/rules/text/js/docs/cspell-fix.md +0 -2
  127. package/rules/text/js/docs/run-dotenv-linter.md +0 -2
  128. package/rules/text/js/docs/run-shellcheck.md +0 -2
  129. package/rules/text/js/docs/run-v8r.md +0 -2
  130. package/rules/text/main.mdc +0 -33
  131. package/rules/tool-surface/docs/main.md +0 -2
  132. package/rules/vue/docs/main.md +0 -2
  133. package/rules/vue/js/docs/packages.md +12 -17
  134. package/rules/vue/js/packages.mjs +41 -1
  135. package/rules/vue/main.mdc +0 -22
  136. package/rules/worktree/docs/main.md +0 -2
  137. package/scripts/docs/auto-rules.md +0 -2
  138. package/scripts/docs/auto-skills.md +0 -2
  139. package/scripts/docs/hook.md +13 -12
  140. package/scripts/docs/post-tool-use-check.md +0 -2
  141. package/scripts/docs/sync-claude-config.md +1 -3
  142. package/scripts/docs/sync-setup-bun-deps-action.md +0 -2
  143. package/scripts/hook.mjs +3 -4
  144. package/scripts/lib/docs/check-mdc-template-refs.md +0 -2
  145. package/scripts/lib/docs/index.md +35 -35
  146. package/scripts/lib/docs/inline-template-links.md +6 -8
  147. package/scripts/lib/docs/list-project-rules-mdc.md +0 -2
  148. package/scripts/lib/docs/list-rule-ids.md +0 -2
  149. package/scripts/lib/docs/mirror-parity.md +8 -10
  150. package/scripts/lib/docs/read-n-cursor-config-lite.md +0 -2
  151. package/scripts/lib/docs/rule-meta.md +0 -2
  152. package/scripts/lib/docs/run-lint.md +0 -2
  153. package/scripts/lib/docs/run-rule-cli.md +0 -2
  154. package/scripts/lib/docs/run-rule.md +0 -2
  155. package/scripts/lib/docs/run-standard-lint.md +0 -2
  156. package/scripts/lib/docs/run-standard-rule.md +0 -2
  157. package/scripts/lib/docs/skill-meta.md +0 -2
  158. package/scripts/lib/docs/timing-summary.md +0 -2
  159. package/scripts/lib/docs/worktree-notice.md +0 -2
  160. package/scripts/lib/fix/docs/analyze-escalation.md +0 -2
  161. package/scripts/lib/fix/docs/index.md +1 -0
  162. package/scripts/lib/fix/docs/llm-worker.md +18 -8
  163. package/scripts/lib/fix/docs/orchestrator.md +10 -16
  164. package/scripts/lib/fix/docs/run-conformance-check.md +0 -2
  165. package/scripts/lib/fix/docs/t0.md +0 -2
  166. package/scripts/lib/fix/docs/verbose-block.md +27 -0
  167. package/scripts/lib/fix/llm-worker.mjs +75 -22
  168. package/scripts/lib/fix/orchestrator.mjs +9 -3
  169. package/scripts/lib/fix/verbose-block.mjs +82 -0
  170. package/scripts/lib/inline-template-links.mjs +32 -22
  171. package/scripts/lib/mirror-parity.mjs +2 -2
  172. package/scripts/sync-claude-config.mjs +7 -4
  173. package/scripts/utils/docs/resolve-js-root.md +0 -2
  174. package/skills/doc-files/SKILL.md +9 -24
  175. package/skills/llm-patch/SKILL.md +4 -4
package/rules/ga/main.mdc CHANGED
@@ -5,34 +5,4 @@ globs: ".github/workflows/*.yml"
5
5
  alwaysApply: false
6
6
  ---
7
7
 
8
- Правило **ga** перевіряє структуру `.github/workflows/`, наявність обов'язкових workflow-файлів і їх відповідність канонам, а також налаштування VS Code та zizmor для роботи з GitHub Actions.
9
-
10
- [ga-workflows](./js/workflows.mdc)
11
-
12
- [ga-workflow_common](./js/workflow_common.mdc)
13
-
14
- [ga-required_workflows](./js/required_workflows.mdc)
15
-
16
- [ga-vscode](./js/vscode.mdc)
17
-
18
- [ga-zizmor](./js/zizmor.mdc)
19
-
20
- [ga-lint_toolchain](./js/lint_toolchain.mdc)
21
-
22
- ## Швидкий gate через conftest
23
-
24
- [ga-workflow_common](./policy/workflow_common/workflow_common.mdc)
25
-
26
- [ga-clean_ga_workflows](./policy/clean_ga_workflows/clean_ga_workflows.mdc)
27
-
28
- [ga-clean_merged_branch](./policy/clean_merged_branch/clean_merged_branch.mdc)
29
-
30
- [ga-lint_ga](./policy/lint_ga/lint_ga.mdc)
31
-
32
- [ga-git_ai](./policy/git_ai/git_ai.mdc)
33
-
34
- [ga-vscode_extensions](./policy/vscode_extensions/vscode_extensions.mdc)
35
-
36
- [ga-vscode_settings](./policy/vscode_settings/vscode_settings.mdc)
37
-
38
- [ga-zizmor_yml](./policy/zizmor_yml/zizmor_yml.mdc)
8
+ Правило **ga** перевіряє структуру `.github/workflows/`, наявність обов'язкових workflow-файлів і їх відповідність канонам, а також налаштування VS Code та zizmor для роботи з GitHub Actions.
@@ -8,8 +8,6 @@ docgen:
8
8
  score: 100
9
9
  ---
10
10
 
11
- ## Огляд
12
-
13
11
  Модуль валідує дані на відповідність політикам, використовуючи конфігурації з meta.json, логіку визначення зацікавленості та контекст. При виконанні як CLI, він завантажує конфігурації, перевіряє білий список, агрегує стан валідації та завершує роботу відповідним кодом.
14
12
 
15
13
  ## Поведінка
@@ -7,8 +7,3 @@ alwaysApply: false
7
7
 
8
8
  Якщо у `.vue` або JavaScript / TypeScript джерелах зустрічається **tagged template literal** з тегом **`gql`**, у корені репозиторію мають бути `.graphqlrc.yml` та запис `graphql.vscode-graphql` у `.vscode/extensions.json`.
9
9
 
10
- [graphql-tooling](./js/tooling.mdc)
11
-
12
- [graphql-vscode-extensions](./js/vscode_extensions.mdc)
13
-
14
- [graphql-vscode-extensions-policy](./policy/vscode_extensions/vscode_extensions.mdc)
@@ -8,8 +8,6 @@ docgen:
8
8
  score: 100
9
9
  ---
10
10
 
11
- ## Огляд
12
-
13
11
  Модуль виконує логіку, визначену у конфігурації `meta.json`. Він валідує дані відповідно до правил, застосовує визначену політику та збирає посилання до MDC. При запуску через публічну функцію `run` ініціюється виконання правила. Модуль є read-only і не виконує операцій запису у файлову систему чи бази даних.
14
12
 
15
13
  ## Поведінка
@@ -6,7 +6,7 @@ resource: npm/rules/hasura/js/
6
6
 
7
7
  # npm/rules/hasura/js
8
8
 
9
- | Файл | Тип |
10
- |---|---|
9
+ | Файл | Тип |
10
+ | ------------------------------------- | --------- |
11
11
  | [internal_urls.mjs](internal_urls.md) | JS Module |
12
- | [migrations.mjs](migrations.md) | JS Module |
12
+ | [migrations.mjs](migrations.md) | JS Module |
@@ -8,8 +8,6 @@ docgen:
8
8
  score: 100
9
9
  ---
10
10
 
11
- ## Огляд
12
-
13
11
  Функція перевіряє вміст директорії міграцій Hasura. Вона гарантує, що в директорії `hasura/migrations` відсутні файли з назвою `down.sql`, оскільки там мають бути лише файли `up.sql` (hasura.mdc).
14
12
 
15
13
  ## Поведінка
@@ -5,14 +5,4 @@ globs: "**/hasura/**,**/*.env"
5
5
  alwaysApply: false
6
6
  ---
7
7
 
8
- Правило охоплює: коректність підключення Hasura у CI-середовищі (внутрішній URL кластера), конвенцію іменування k8s-сервісів та структуру директорій міграцій.
9
-
10
- [hasura-internal_urls](./js/internal_urls.mdc)
11
-
12
- [hasura-svc_hl](./js/svc_hl.mdc)
13
-
14
- [hasura-migrations](./js/migrations.mdc)
15
-
16
- ## Швидкий gate через conftest
17
-
18
- [hasura-svc_hl](./policy/svc_hl/svc_hl.mdc)
8
+ Правило охоплює: коректність підключення Hasura у CI-середовищі (внутрішній URL кластера), конвенцію іменування k8s-сервісів та структуру директорій міграцій.
@@ -8,8 +8,6 @@ docgen:
8
8
  score: 100
9
9
  ---
10
10
 
11
- ## Огляд
12
-
13
11
  Модуль виконує перевірку на основі логіки правил, використовуючи конфігурації з meta.json, політики та посилання на MDC. При запуску як окрема утиліта, він завантажує конфігурації, застосовує білі списки для фільтрації та формує зведений звіт. Результат виконання визначає код виходу процесу. Кешування відбувається у межах прогону. Модуль є Read-only, тобто не здійснює записів у файлову систему чи бази даних.
14
12
 
15
13
  ## Поведінка
@@ -5,12 +5,4 @@ globs: "**/*.{png,jpg,jpeg,gif,avif,vue,html}"
5
5
  alwaysApply: false
6
6
  ---
7
7
 
8
- Правило забезпечує, що кожне raster-зображення (`png`, `jpg`, `jpeg`, `gif`), на яке посилаються `.vue`/`.html` файли, має AVIF-двійник і що посилання переписані на нього. Генерація, rewrite і cleanup AVIF-сиріт виконуються автоматично через `npx @nitra/cursor fix image-avif`.
9
-
10
- [image-avif-avif_generation](./js/avif_generation.mdc)
11
-
12
- [image-avif-package_json_optout](./js/package_json_optout.mdc)
13
-
14
- ## Швидкий gate через conftest
15
-
16
- [image-avif-package_json](./policy/package_json/package_json.mdc)
8
+ Правило забезпечує, що кожне raster-зображення (`png`, `jpg`, `jpeg`, `gif`), на яке посилаються `.vue`/`.html` файли, має AVIF-двійник і що посилання переписані на нього. Генерація, rewrite і cleanup AVIF-сиріт виконуються автоматично через `npx @nitra/cursor fix image-avif`.
@@ -8,8 +8,6 @@ docgen:
8
8
  score: 90
9
9
  ---
10
10
 
11
- ## Огляд
12
-
13
11
  Модуль забезпечує механізми для виконання та валідації контенту відповідно до визначених правил. Функція `run` виконує перевірку відповідності контенту визначеним критеріям у межах поточного контексту прогону. Функція `lint` виконує виявлення або стиснення зображень залежно від режиму `readOnly`.
14
12
 
15
13
  ## Поведінка
@@ -8,5 +8,4 @@ resource: npm/rules/image-compress/js/
8
8
 
9
9
  | Файл | Тип |
10
10
  | ------------------------------------- | --------- |
11
- | [lint.mjs](lint.md) | JS Module |
12
11
  | [package_setup.mjs](package_setup.md) | JS Module |
@@ -7,12 +7,4 @@ alwaysApply: false
7
7
 
8
8
  CLI [`@nitra/minify-image`](https://www.npmjs.com/package/@nitra/minify-image) (≥ **4.0.1**) запускається через `npx` і **не** додається в `dependencies` / `devDependencies`. Запуск — через **`n-cursor lint image-compress`**: локально (fix) виконує `npx @nitra/minify-image --src=. --write`, у `--read-only` виконує `npx @nitra/minify-image --src=. --json` і падає, якщо `summary.needsCompression > 0`. **AVIF-генерація (`--avif`) у `image-compress` не входить** — її виконує окреме правило `image-avif`.
9
9
 
10
- Окремий workflow `lint-image.yml` створювати не треба; якщо потрібен CI-gate для зображень, використовуй `n-cursor lint image-compress --read-only`.
11
-
12
- [image-compress-package_setup](./js/package_setup.mdc)
13
-
14
- [image-compress-package_json](./js/package_json.mdc)
15
-
16
- ## Швидкий gate через conftest
17
-
18
- [image-compress-package_json](./policy/package_json/package_json.mdc)
10
+ Окремий workflow `lint-image.yml` створювати не треба; якщо потрібен CI-gate для зображень, використовуй `n-cursor lint image-compress --read-only`.
@@ -8,8 +8,6 @@ docgen:
8
8
  score: 100
9
9
  ---
10
10
 
11
- ## Огляд
12
-
13
11
  Модуль забезпечує виконання функцій `run`, `filterJsFiles` та `lint` для аналізу кодової бази. Він виконує стандартну перевірку проєкту, відбираючи файли з розширеннями JavaScript за допомогою `filterJsFiles` та запускаючи перевірку JS-коду за допомогою `lint`.
14
12
 
15
13
  ## Поведінка
@@ -11,7 +11,7 @@ import {
11
11
  dynamicImportModule,
12
12
  langFromPath,
13
13
  requireCallModule,
14
- walkAstWithAncestors,
14
+ walkAstWithAncestors
15
15
  } from '../../../scripts/utils/ast-scan-utils.mjs'
16
16
 
17
17
  const JS_SOURCE_RE = /\.(?:[cm]?[jt]sx?)$/u
@@ -60,9 +60,13 @@ export async function check(cwdParam = process.cwd()) {
60
60
  const ignorePaths = await loadCursorIgnorePaths(cwd)
61
61
 
62
62
  const files = []
63
- await walkDir(cwd, p => {
64
- if (JS_SOURCE_RE.test(p)) files.push(p)
65
- }, ignorePaths)
63
+ await walkDir(
64
+ cwd,
65
+ p => {
66
+ if (JS_SOURCE_RE.test(p)) files.push(p)
67
+ },
68
+ ignorePaths
69
+ )
66
70
 
67
71
  let violations = 0
68
72
  for (const absPath of files) {
@@ -8,8 +8,6 @@ docgen:
8
8
  score: 100
9
9
  ---
10
10
 
11
- ## Огляд
12
-
13
11
  Модуль виконує валідацію конфігураційних файлів, включаючи `package.json`, `.oxlintrc.json`, `knip.json`, `knip-canonical.json` та `.eslintrc.json`. Він перевіряє відповідність структури та конфігурацій встановленим стандартам. (js.mdc) (text.mdc)
14
12
 
15
13
  ## Поведінка
@@ -3,28 +3,26 @@ type: JS Module
3
3
  title: dep-policy.mjs
4
4
  resource: npm/rules/js/js/dep-policy.mjs
5
5
  docgen:
6
- crc: 82035584
6
+ crc: 020620cb
7
7
  model: omlx/gemma-4-e4b-it-OptiQ-4bit
8
8
  score: 100
9
9
  ---
10
10
 
11
- ## Огляд
12
-
13
- Модуль сканує JavaScript та TypeScript файли проєкту для перевірки відповідності політикам залежностей. Він знаходить усі імпорти у файлах і порівнює їх із переліком заборонених специфікаторів. При виявленні порушень політики, вони реєструються. Модуль працює у режимі, що перехоплює помилки (fail-safe), і не кидає винятків назовні. Він є лише для читання (Read-only) і не змінює файлову систему чи бази даних. Результат роботи визначається кодом виходу, що інформує про наявність чи відсутність порушень політики (dep-policy.mdc) та успішну перевірку (js.mdc).
11
+ Модуль сканує файли з розширеннями JS/TS у проєкті. Він перевіряє, чи не містять ці файли імпортів, заборонених відповідно до політики (dep-policy.mdc). Модуль виконує перевірку у режимі лише для читання. У разі виявлення порушень, він реєструє їх у звіті. Модуль перехоплює всі можливі помилки (fail-safe) і не генерує винятків назовні. Результат роботи відображається через код виходу, що інформує про статус перевірки (js.mdc).
14
12
 
15
13
  ## Поведінка
16
14
 
17
15
  1. Ініціалізує звітність.
18
16
  2. Визначає кореневу директорію проєкту.
19
- 3. Зчитує список шляхів, які слід ігнорувати під час сканування.
20
- 4. Знаходить усі файли з розширеннями JavaScript/TypeScript у кореневій директорії, ігноруючи визначені шляхи.
21
- 5. Для кожного знайденого файлу:
22
- а. Зчитує вміст файлу.
23
- б. Витягує всі імпортовані специфікатори з вмісту файлу.
24
- в. Перевіряє кожен витягнутий специфікатор на відповідність списку заборонених специфікаторів (dep-policy.mdc).
25
- г. Якщо специфікатор заборонений, реєструє помилку, вказуючи відносний шлях до файлу та заборонений імпорт. Збільшує лічильник порушень.
17
+ 3. Завантажує списки шляхів, які слід ігнорувати.
18
+ 4. Збирає список усіх файлів з розширеннями JS/TS у кореневій директорії, ігноруючи визначені шляхи.
19
+ 5. Для кожного зібраного файлу:
20
+ а. Зчитує вміст файлу.
21
+ б. Витягує з вмісту всі імпортовані специфікатори (статичні, динамічні та через `require`).
22
+ в. Для кожного витягнутого специфікатора перевіряє, чи він є забороненим відповідно до політики (dep-policy.mdc).
23
+ г. Якщо специфікатор заборонений, реєструє помилку у звіті, вказуючи шлях до файлу та заборонений імпорт. Збільшує лічильник порушень.
26
24
  6. Якщо порушень не знайдено, реєструє повідомлення про успішну перевірку (js.mdc).
27
- 7. Повертає код виходу, що відображає наявність порушень.
25
+ 7. Повертає код виходу звіту.
28
26
 
29
27
  ## Публічний API
30
28
 
@@ -6,10 +6,10 @@ resource: npm/rules/js/js/
6
6
 
7
7
  # npm/rules/js/js
8
8
 
9
- | Файл | Тип |
10
- |---|---|
11
- | [check.mjs](check.md) | JS Module |
12
- | [dep-policy.mjs](dep-policy.md) | JS Module |
9
+ | Файл | Тип |
10
+ | ------------------------------------- | --------- |
11
+ | [check.mjs](check.md) | JS Module |
12
+ | [dep-policy.mjs](dep-policy.md) | JS Module |
13
13
  | [lint-findings.mjs](lint-findings.md) | JS Module |
14
- | [tooling.mjs](tooling.md) | JS Module |
14
+ | [tooling.mjs](tooling.md) | JS Module |
15
15
  | [utils_imports.mjs](utils_imports.md) | JS Module |
@@ -8,8 +8,6 @@ docgen:
8
8
  score: 95
9
9
  ---
10
10
 
11
- ## Огляд
12
-
13
11
  Визначає шляхи до канонічних JSON-файлів для інструментів oxlint та knip через OXLINT_CANONICAL_JSON_PATH та KNIP_CANONICAL_JSON_PATH. Також перевіряє відповідність конфігураційного файлу .oxlintrc.json значенням, встановленим у oxlint-canonical.json, за допомогою verifyOxlintRcAgainstCanonical.
14
12
 
15
13
  ## Поведінка
@@ -8,8 +8,6 @@ docgen:
8
8
  score: 100
9
9
  ---
10
10
 
11
- ## Огляд
12
-
13
11
  Модуль сканує монорепозиторій для пошуку каталогів `utils` та аналізу їхнього вмісту. Аналіз файлів JS/TS у цих каталогах здійснюється на відповідність шаблону забороненого відносного імпорту, що базується на конфігурації, визначеній у `.n-cursor.json`. При виявленні порушень, система генерує повідомлення, позначене як (js.mdc).
14
12
 
15
13
  ## Поведінка
package/rules/js/main.mdc CHANGED
@@ -7,38 +7,7 @@ version: '1.30'
7
7
 
8
8
  **oxlint**, **ESLint**, **jscpd**, **knip**. Запуск — **`n-cursor lint js`** (локально; у CI — `--read-only`, без **`--fix`** для oxlint/eslint). Без **prettier** і **@nitra/prettier-config**.
9
9
 
10
- [js-file-extensions](./js/file-extensions.mdc)
11
-
12
- [js-package-json](./js/package-json.mdc)
13
-
14
- [js-eslint-config](./js/eslint-config.mdc)
15
-
16
- [js-oxlintrc](./js/oxlintrc.mdc)
17
-
18
- [js-extensions](./js/extensions.mdc)
19
-
20
- [js-jscpd](./js/jscpd.mdc)
21
-
22
- [js-knip](./js/knip.mdc)
23
-
24
- [js-dep-policy](./js/dep-policy.mdc)
25
-
26
- [js-lint-js-workflow](./js/lint-js-workflow.mdc)
27
-
28
- [js-utils-lib-structure](./js/utils-lib-structure.mdc)
29
-
30
- [js-for-in](./js/for-in.mdc)
31
-
32
- [js-tests](./js/tests.mdc)
33
-
34
10
  ## Швидкий gate через conftest
35
11
 
36
12
  Rego-пакети у `policy/` — запускаються `npx @nitra/cursor fix js` або `conftest`:
37
13
 
38
- [js-policy-package_json](./policy/package_json/package_json.mdc)
39
-
40
- [js-policy-jscpd](./policy/jscpd/jscpd.mdc)
41
-
42
- [js-policy-lint_js_yml](./policy/lint_js_yml/lint_js_yml.mdc)
43
-
44
- [js-policy-vscode_extensions](./policy/vscode_extensions/vscode_extensions.mdc)
@@ -8,8 +8,6 @@ docgen:
8
8
  score: 90
9
9
  ---
10
10
 
11
- ## Огляд
12
-
13
11
  Модуль виконує перевірку, застосовуючи правила та політики. При виклику публічної функції `run` він завантажує конфігурації, зокрема `meta.json`, застосовує білі списки та підбиває підсумки. Модуль є Read-only, тобто не пише у файлову систему чи базу даних. Під час роботи відбувається кешування даних у межах одного прогону. Результат перевірки визначає код виходу процесу.
14
12
 
15
13
  ## Поведінка
@@ -3,39 +3,34 @@ type: JS Module
3
3
  title: safety.mjs
4
4
  resource: npm/rules/js-bun-db/js/safety.mjs
5
5
  docgen:
6
- crc: eaeb52bc
6
+ crc: e828ee4a
7
+ model: omlx/gemma-4-e4b-it-OptiQ-4bit
7
8
  score: 100
8
9
  ---
9
10
 
10
- Огляд
11
+ Модуль сканує репозиторій для валідації безпечності використання Bun SQL. Він шукає всі файли `package.json` та JS/TS джерела, щоб перевірити відповідність патернів Bun SQL правилам, визначеним у конфігурації, що спирається на `package.json`.
11
12
 
12
- Файл перевіряє шляхи до файлів та залежностей, пов'язаних з Bun SQL та бібліотекою `pg`. Файл збирає метадані про використання `pg` та механізми LISTEN/NOTIFY. (js-bun-db.mdc)
13
+ Поведінка:
14
+
15
+ - Перевіряє відповідність патернів Bun SQL встановленим правилам (js-bun-db.mdc).
13
16
 
14
17
  ## Поведінка
15
18
 
16
- 1. Завантажити шляхи до файлів з коду
17
- 2. Просканувати джерела за патернами Bun SQL
18
- 3. Зібрати метадані про використання `pg` та LISTEN/NOTIFY
19
- 4. Перевірити залежності `pg` та використання LISTEN/NOTIFY
20
- 5. Перевірити імпорти `pg` та використання LISTEN/NOTIFY
21
- 6. Перевірити наявність `package.json` для залежностей `pg`
22
- 7. Перевірити використання `import { sql|SQL } from 'bun'`
23
- 8. Перевірити відсутність створення `new SQL` всередині функцій
24
- 9. Перевірити використання `sql.unsafe` без маркерів дозволу
25
- 10. Перевірити використання `sql.unsafe` з template-літералами
26
- 11. Перевірити використання `pg-leftover` викликів
27
- 12. Перевірити використання `findBunSqlUnsafeBunSqlDynamicSqlListInText`
28
- 13. Перевірити використання `findUnsafeBunSqlInListMissingEmptyGuardInText`
29
- 14. Перевірити використання `findPgFormatShimDefinitionInText`
30
- 15. Перевірити використання `findPgFormatLikeQueryWrapperInText`
31
- 16. Перевірити наявність використання `import { sql } from 'bun'`
19
+ 1. Викликається `check` для початку перевірки.
20
+ 2. Перевіряється наявність `package.json` у корені репозиторію. Якщо відсутній, перевірка припиняється.
21
+ 3. Завантажуються конфігураційні шляхи, які ігноруються під час обходу.
22
+ 4. Знаходяться всі файли `package.json` у репозиторії. Якщо жоден не знайдено, перевірка припиняється.
23
+ 5. Знаходяться всі JS/TS джерела для сканування патернів Bun SQL. Якщо жоден не знайдено, перевірка припиняється.
24
+ 6. Скануються знайдені JS/TS джерела на небезпечні патерни Bun SQL. Збираються метадані про використання Bun SQL та про використання бібліотеки `pg` (LISTEN/NOTIFY).
25
+ 7. Перевіряється залежність `pg` у знайдених `package.json` на відповідність правилу: якщо `pg` є залежністю, у коді має бути хоча б одне використання LISTEN/NOTIFY.
26
+ 8. Перевіряється кожен файл, що імпортує `pg`. Якщо у ньому немає використання LISTEN/NOTIFY, реєструється порушення.
27
+ 9. Після завершення сканування та перевірок, реєструються всі знайдені порушення, пов'язані з Bun SQL (наприклад, створення `new SQL` всередині функцій, використання `sql.unsafe` без маркерів, проблеми з динамічними списками тощо).
28
+ 10. Якщо всі перевірки пройдені успішно, реєструється повідомлення про відповідність правилу `js-bun-db.mdc`.
32
29
 
33
30
  ## Публічний API
34
31
 
35
- check — Перевіряє відповідність проєкту правилу js-bun-db.mdc
32
+ check — порівнює структуру проєкту з вимогами, описаними у js-bun-db.mdc
36
33
 
37
34
  ## Гарантії поведінки
38
35
 
39
- - Read-only: файл не виконує операцій запису у файлову систему.
40
- - Перехоплює помилки і не пропускає винятків назовні (fail-safe).
41
- - Не звертається до мережі.
36
+ - Read-only: не виконує операцій запису (ФС/БД).
@@ -9,10 +9,12 @@ import {
9
9
  findBunSqlPgLeftoverCallInText,
10
10
  findBunSqlUnsafeUseWithoutAllowMarkerInText,
11
11
  findBunSqlUnsafeWithInterpolatedTemplateInText,
12
+ findJsonStringifyBeforeJsonbInText,
12
13
  findPgFormatLikeQueryWrapperInText,
13
14
  findPgFormatShimDefinitionInText,
14
15
  findPgLibImportInText,
15
16
  findPgListenNotifyUsageInText,
17
+ findSqlArrayWithoutTypeArgInText,
16
18
  findUnsafeBunSqlDynamicSqlListInText,
17
19
  findUnsafeBunSqlInListMissingEmptyGuardInText,
18
20
  isBunSqlScanSourceFile,
@@ -83,7 +85,9 @@ async function scanSourcesForBunSqlPatterns(sourcePaths, repoRoot, reporter) {
83
85
  inListGuard: 0,
84
86
  pgLeftover: 0,
85
87
  pgFormatShim: 0,
86
- queryWrapper: 0
88
+ queryWrapper: 0,
89
+ jsonStringifyJsonb: 0,
90
+ sqlArrayNoType: 0
87
91
  }
88
92
  let hasBunSqlImport = false
89
93
  /** @type {{ rel: string, imports: { line: number, snippet: string }[], listenNotify: { line: number, snippet: string, kind: string }[] }[]} */
@@ -127,7 +131,7 @@ function collectPgUsageForFile(content, rel, pgUsage) {
127
131
  * @param {string} content вміст файлу
128
132
  * @param {string} rel posix-шлях відносно `repoRoot`
129
133
  * @param {(msg: string) => void} fail callback при помилці
130
- * @param {{ perRequest: number, unsafeCall: number, dynamicList: number, inListGuard: number, pgLeftover: number, pgFormatShim: number, queryWrapper: number }} counts акумулятори
134
+ * @param {{ perRequest: number, unsafeCall: number, unsafeTemplateInterp: number, dynamicList: number, inListGuard: number, pgLeftover: number, pgFormatShim: number, queryWrapper: number, jsonStringifyJsonb: number, sqlArrayNoType: number }} counts акумулятори
131
135
  * @returns {void}
132
136
  */
133
137
  function scanFileForBunSqlPatterns(content, rel, fail, counts) {
@@ -202,6 +206,22 @@ function scanFileForBunSqlPatterns(content, rel, fail, counts) {
202
206
  `sql\`...\${value}...\` (js-bun-db.mdc): ${v.snippet}`
203
207
  )
204
208
  }
209
+ for (const v of findJsonStringifyBeforeJsonbInText(content, rel)) {
210
+ counts.jsonStringifyJsonb++
211
+ fail(
212
+ `js-bun-db: ${rel}:${v.line} — JSON.stringify(...) перед ::jsonb зайвий: Bun SQL серіалізує ` +
213
+ `об'єкти/масиви у JSON автоматично, явний stringify призводить до подвійної серіалізації ` +
214
+ `(js-bun-db.mdc query-safety): ${v.snippet}`
215
+ )
216
+ }
217
+ for (const v of findSqlArrayWithoutTypeArgInText(content, rel)) {
218
+ counts.sqlArrayNoType++
219
+ fail(
220
+ `js-bun-db: ${rel}:${v.line} — sql.array(arr) без другого аргументу типу — ` +
221
+ `вкажи явний pg-тип: sql.array(arr, 'int8') / sql.array(arr, 'uuid') тощо ` +
222
+ `(js-bun-db.mdc sql-array): ${v.snippet}`
223
+ )
224
+ }
205
225
  }
206
226
 
207
227
  /**
@@ -338,7 +358,9 @@ export async function check(cwd = process.cwd()) {
338
358
  inListGuard,
339
359
  pgLeftover,
340
360
  pgFormatShim,
341
- queryWrapper
361
+ queryWrapper,
362
+ jsonStringifyJsonb,
363
+ sqlArrayNoType
342
364
  } = await scanSourcesForBunSqlPatterns(sourcePaths, repoRoot, reporter)
343
365
 
344
366
  const { pgDepFails, pgImportFails, pgDepsFound, listenNotifyEvidence } = await checkPgDependencyAndUsage(
@@ -396,6 +418,12 @@ export async function check(cwd = process.cwd()) {
396
418
  if (queryWrapper === 0) {
397
419
  pass('js-bun-db: немає query(text, params)-обгорток над unsafe(...) у файлах з Bun SQL')
398
420
  }
421
+ if (jsonStringifyJsonb === 0) {
422
+ pass('js-bun-db: немає JSON.stringify(...) перед ::jsonb — Bun SQL серіалізує автоматично')
423
+ }
424
+ if (sqlArrayNoType === 0) {
425
+ pass('js-bun-db: усі sql.array() мають явний аргумент типу')
426
+ }
399
427
 
400
428
  return reporter.getExitCode()
401
429
  }
@@ -927,3 +927,126 @@ function kindFromListenNotifyMatch(text) {
927
927
  export function isBunSqlScanSourceFile(relativePathPosix) {
928
928
  return SOURCE_FILE_RE.test(relativePathPosix) && !relativePathPosix.endsWith('.d.ts')
929
929
  }
930
+
931
+ // Імена відомих SQL-інстансів, для яких перевіряємо .array() без типу.
932
+ const SQL_INSTANCE_NAMES = new Set(['sql', 'pgWrite', 'pgRead'])
933
+
934
+ /**
935
+ * Чи це виклик `JSON.stringify(...)` (JSON.stringify через MemberExpression).
936
+ * @param {unknown} node AST node
937
+ * @returns {boolean}
938
+ */
939
+ function isJsonStringifyCall(node) {
940
+ if (!node || typeof node !== 'object' || node.type !== 'CallExpression') return false
941
+ const callee = node.callee
942
+ if (!callee || callee.type !== 'MemberExpression' || callee.computed) return false
943
+ const obj = callee.object
944
+ const prop = callee.property
945
+ return (
946
+ !!obj &&
947
+ obj.type === 'Identifier' &&
948
+ obj.name === 'JSON' &&
949
+ !!prop &&
950
+ prop.type === 'Identifier' &&
951
+ prop.name === 'stringify'
952
+ )
953
+ }
954
+
955
+ /**
956
+ * Знаходить виклики `JSON.stringify(...)::jsonb` всередині SQL template literal-ів.
957
+ * Bun SQL серіалізує об'єкти/масиви у JSON автоматично — явний `JSON.stringify`
958
+ * перед `::jsonb` призводить до подвійної серіалізації (js-bun-db.mdc).
959
+ * @param {string} content вихідний код
960
+ * @param {string} [virtualPath] шлях для вибору lang
961
+ * @returns {{ line: number, snippet: string }[]} список порушень
962
+ */
963
+ export function findJsonStringifyBeforeJsonbInText(content, virtualPath = 'scan.ts') {
964
+ const program = parseProgramOrNull(content, virtualPath)
965
+ if (!program) return []
966
+
967
+ /** @type {{ line: number, snippet: string }[]} */
968
+ const out = []
969
+
970
+ walkAstWithAncestors(program, [], node => {
971
+ let template = null
972
+ if (node.type === 'TemplateLiteral') template = node
973
+ else if (node.type === 'TaggedTemplateExpression') template = node.quasi
974
+ if (!template || typeof template !== 'object' || template.type !== 'TemplateLiteral') return
975
+
976
+ const expressions = template.expressions
977
+ const quasis = template.quasis
978
+ if (!Array.isArray(expressions) || !Array.isArray(quasis)) return
979
+
980
+ for (const [i, expr] of expressions.entries()) {
981
+ // Перевіряємо прямий JSON.stringify(...) і JSON.stringify всередині sql.array(...)
982
+ const isDirectStringify = isJsonStringifyCall(expr)
983
+ // sql.array(batch.map(r => JSON.stringify(...)), 'jsonb')
984
+ const hasSqlArrayStringify =
985
+ !isDirectStringify &&
986
+ expr.type === 'CallExpression' &&
987
+ Array.isArray(expr.arguments) &&
988
+ expr.arguments.some(arg => {
989
+ if (isJsonStringifyCall(arg)) return true
990
+ // .map(r => JSON.stringify(...))
991
+ if (arg.type === 'CallExpression' && Array.isArray(arg.arguments)) {
992
+ const cb = arg.arguments[0]
993
+ if (!cb) return false
994
+ const body = cb.type === 'ArrowFunctionExpression' || cb.type === 'FunctionExpression' ? cb.body : null
995
+ if (body && isJsonStringifyCall(body)) return true
996
+ }
997
+ return false
998
+ })
999
+
1000
+ if (!isDirectStringify && !hasSqlArrayStringify) continue
1001
+
1002
+ // Quasi після expr (quasi[i+1]) — текст одразу після закриваючого }
1003
+ const nextQuasi = quasis[i + 1]
1004
+ const rawAfter =
1005
+ nextQuasi && typeof nextQuasi === 'object' && nextQuasi.value && typeof nextQuasi.value.raw === 'string'
1006
+ ? nextQuasi.value.raw
1007
+ : ''
1008
+
1009
+ if (/^\s*::jsonb/u.test(rawAfter) || hasSqlArrayStringify) {
1010
+ out.push({
1011
+ line: offsetToLine(content, expr.start),
1012
+ snippet: normalizeSnippet(content.slice(expr.start, expr.end))
1013
+ })
1014
+ }
1015
+ }
1016
+ })
1017
+ return out
1018
+ }
1019
+
1020
+ /**
1021
+ * Знаходить виклики `sql.array(arr)` / `pgWrite.array(arr)` / `pgRead.array(arr)` без
1022
+ * обов'язкового другого аргументу (типу pg-елемента). Без типу Bun не може вивести
1023
+ * pg-тип, що призводить до mismatch (js-bun-db.mdc).
1024
+ * @param {string} content вихідний код
1025
+ * @param {string} [virtualPath] шлях для вибору lang
1026
+ * @returns {{ line: number, snippet: string }[]} список порушень
1027
+ */
1028
+ export function findSqlArrayWithoutTypeArgInText(content, virtualPath = 'scan.ts') {
1029
+ const program = parseProgramOrNull(content, virtualPath)
1030
+ if (!program) return []
1031
+
1032
+ /** @type {{ line: number, snippet: string }[]} */
1033
+ const out = []
1034
+
1035
+ walkAstWithAncestors(program, [], node => {
1036
+ if (!node || node.type !== 'CallExpression') return
1037
+ const callee = node.callee
1038
+ if (!callee || callee.type !== 'MemberExpression' || callee.computed) return
1039
+ const prop = callee.property
1040
+ if (!prop || prop.type !== 'Identifier' || prop.name !== 'array') return
1041
+ const obj = callee.object
1042
+ if (!obj || obj.type !== 'Identifier' || !SQL_INSTANCE_NAMES.has(obj.name)) return
1043
+ const args = node.arguments
1044
+ if (!Array.isArray(args) || args.length !== 1) return
1045
+
1046
+ out.push({
1047
+ line: offsetToLine(content, node.start),
1048
+ snippet: normalizeSnippet(content.slice(node.start, node.end))
1049
+ })
1050
+ })
1051
+ return out
1052
+ }