@nitra/cursor 1.11.0 → 1.11.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.
Files changed (30) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/bin/n-cursor.js +2 -2
  3. package/package.json +1 -4
  4. package/rules/abie/utils/k8s-tree.mjs +1 -1
  5. package/rules/adr/js/{check.mjs → hooks/check.mjs} +2 -2
  6. package/rules/bun/js/{check.mjs → layout/check.mjs} +1 -1
  7. package/rules/capacitor/js/{check.mjs → platforms/check.mjs} +1 -1
  8. package/rules/changelog/js/{check.mjs → consistency/check.mjs} +2 -2
  9. package/rules/docker/js/{check.mjs → lint/check.mjs} +5 -5
  10. package/rules/ga/js/lint.mjs +1 -1
  11. package/rules/ga/js/{check.mjs → workflows/check.mjs} +4 -4
  12. package/rules/graphql/js/{check.mjs → tooling/check.mjs} +5 -5
  13. package/rules/hasura/js/{check.mjs → internal_urls/check.mjs} +4 -4
  14. package/rules/image-avif/js/{check.mjs → avif_generation/check.mjs} +5 -5
  15. package/rules/image-compress/js/{check.mjs → package_setup/check.mjs} +1 -1
  16. package/rules/js-bun-db/js/{check.mjs → safety/check.mjs} +5 -5
  17. package/rules/js-bun-redis/js/{check.mjs → imports/check.mjs} +4 -4
  18. package/rules/js-lint/js/{check.mjs → tooling/check.mjs} +16 -2
  19. package/rules/js-mssql/js/{check.mjs → deps/check.mjs} +5 -5
  20. package/rules/js-run/js/{check.mjs → runtime/check.mjs} +10 -10
  21. package/rules/k8s/js/{check.mjs → manifests/check.mjs} +4 -4
  22. package/rules/nginx-default-tpl/js/{check.mjs → template/check.mjs} +5 -5
  23. package/rules/npm-module/js/{check.mjs → package_structure/check.mjs} +4 -4
  24. package/rules/php/js/{check.mjs → tooling/check.mjs} +1 -1
  25. package/rules/style-lint/js/{check.mjs → tooling/check.mjs} +1 -1
  26. package/rules/tauri/js/{check.mjs → tooling/check.mjs} +2 -2
  27. package/rules/text/js/{check.mjs → formatting/check.mjs} +2 -2
  28. package/rules/vue/js/{check.mjs → packages/check.mjs} +5 -5
  29. package/scripts/utils/discover-checkable-rules.mjs +5 -22
  30. package/scripts/utils/run-rule.mjs +1 -5
package/CHANGELOG.md CHANGED
@@ -4,6 +4,14 @@
4
4
 
5
5
  Формат — [Keep a Changelog](https://keepachangelog.com/uk/1.1.0/), нумерація — [SemVer](https://semver.org/lang/uk/).
6
6
 
7
+ ## [1.11.1] - 2026-05-15
8
+
9
+ ### Fixed
10
+
11
+ - **`npm/bin/n-cursor.js`** — `runSync()` (entry для `npx @nitra/cursor` без аргументів) шукав
12
+ `<packageRoot>/mdc` після того, як phase 1-4 перейменував каталог у `rules/`. Виправлено: тепер
13
+ вказує на коректний шлях `<packageRoot>/rules` — більше не кидає «Не знайдено каталог правил пакету».
14
+
7
15
  ## [1.11.0] - 2026-05-15
8
16
 
9
17
  ### Added
package/bin/n-cursor.js CHANGED
@@ -945,7 +945,7 @@ async function runSyncStep(prefix, action) {
945
945
  /**
946
946
  * Копіює керовані `.mdc` файли з пакету до `.cursor/rules`.
947
947
  * @param {string[]} rules список rules з конфігу
948
- * @param {string} bundledRulesDir каталог `mdc` пакету-джерела
948
+ * @param {string} bundledRulesDir каталог `rules` пакету-джерела
949
949
  * @param {string} rulesDir абсолютний шлях до `.cursor/rules`
950
950
  * @returns {Promise<{ successCount: number, failCount: number }>} статистика копіювання
951
951
  */
@@ -1207,7 +1207,7 @@ async function runSync() {
1207
1207
 
1208
1208
  await reexecIfPackageVersionChanged(effectivePackageRoot)
1209
1209
 
1210
- const bundledRulesDir = join(effectivePackageRoot, 'mdc')
1210
+ const bundledRulesDir = join(effectivePackageRoot, 'rules')
1211
1211
  const bundledSkillsDir = join(effectivePackageRoot, 'skills')
1212
1212
  const bundledAgentsTemplatePath = join(effectivePackageRoot, AGENTS_TEMPLATE_FILE)
1213
1213
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nitra/cursor",
3
- "version": "1.11.0",
3
+ "version": "1.11.1",
4
4
  "description": "CLI для завантаження cursor-правил (префікс n-) у локальний репозиторій",
5
5
  "keywords": [
6
6
  "cli",
@@ -51,8 +51,5 @@
51
51
  "engines": {
52
52
  "bun": ">=1.3",
53
53
  "node": ">=25"
54
- },
55
- "devDependencies": {
56
- "@nitra/cursor": "^1.9.22"
57
54
  }
58
55
  }
@@ -9,7 +9,7 @@
9
9
  */
10
10
  import { dirname, relative } from 'node:path'
11
11
 
12
- import { pathHasK8sSegment } from '../../k8s/js/check.mjs'
12
+ import { pathHasK8sSegment } from '../../k8s/js/manifests/check.mjs'
13
13
  import { walkDir } from '../../../scripts/utils/walkDir.mjs'
14
14
  import { isDeploymentDoc, readAndParseYamlDocs } from './yaml.mjs'
15
15
 
@@ -22,7 +22,7 @@ import { delimiter, dirname, join } from 'node:path'
22
22
  import { env } from 'node:process'
23
23
  import { fileURLToPath } from 'node:url'
24
24
 
25
- import { createCheckReporter } from '../../../scripts/utils/check-reporter.mjs'
25
+ import { createCheckReporter } from '../../../../scripts/utils/check-reporter.mjs'
26
26
 
27
27
  /** Один hook-артефакт: bash-скрипт + його лог-файл, які перевіряємо однотипно. */
28
28
  const HOOK_ARTIFACTS = /** @type {const} */ ([
@@ -34,7 +34,7 @@ const PROJECT_SETTINGS_PATH = '.claude/settings.json'
34
34
  const EOL_RE = /\r?\n/u
35
35
 
36
36
  const here = dirname(fileURLToPath(import.meta.url))
37
- const BUNDLED_HOOKS_DIR = join(here, '..', '..', '..', '.claude-template', 'hooks')
37
+ const BUNDLED_HOOKS_DIR = join(here, '..', '..', '..', '..', '.claude-template', 'hooks')
38
38
 
39
39
  /**
40
40
  * Відносний шлях до managed hook-скрипта у проєкті.
@@ -18,7 +18,7 @@
18
18
  import { existsSync } from 'node:fs'
19
19
  import { readFile } from 'node:fs/promises'
20
20
 
21
- import { createCheckReporter } from '../../../scripts/utils/check-reporter.mjs'
21
+ import { createCheckReporter } from '../../../../scripts/utils/check-reporter.mjs'
22
22
 
23
23
  // Перевірка `devDependencies` кореневого `package.json` (дозволено лише `@nitra/*`)
24
24
  // — у rego (`npm/policy/bun/package_json/`). JS-копії `isAllowedRootDevDependency`
@@ -25,7 +25,7 @@ import { existsSync } from 'node:fs'
25
25
  import { readdir, readFile } from 'node:fs/promises'
26
26
  import { join, relative } from 'node:path'
27
27
 
28
- import { createCheckReporter } from '../../../scripts/utils/check-reporter.mjs'
28
+ import { createCheckReporter } from '../../../../scripts/utils/check-reporter.mjs'
29
29
 
30
30
  /** Мінімальна допустима мажорна версія Capacitor (capacitor.mdc) */
31
31
  const MIN_CAPACITOR_MAJOR = 8
@@ -27,8 +27,8 @@ import { readFile } from 'node:fs/promises'
27
27
  import { join } from 'node:path'
28
28
  import { promisify } from 'node:util'
29
29
 
30
- import { createCheckReporter } from '../../../scripts/utils/check-reporter.mjs'
31
- import { getMonorepoPackageRootDirs } from '../../../scripts/utils/workspaces.mjs'
30
+ import { createCheckReporter } from '../../../../scripts/utils/check-reporter.mjs'
31
+ import { getMonorepoPackageRootDirs } from '../../../../scripts/utils/workspaces.mjs'
32
32
 
33
33
  const execFileAsync = promisify(execFile)
34
34
 
@@ -30,11 +30,11 @@
30
30
  import { readFile } from 'node:fs/promises'
31
31
  import { basename } from 'node:path'
32
32
 
33
- import { getMirrorGcrHint, getFromImageToken } from '../../../scripts/utils/docker-mirror.mjs'
34
- import { lintDockerfileWithHadolint, posixRel } from '../../../scripts/utils/docker-hadolint.mjs'
35
- import { createCheckReporter } from '../../../scripts/utils/check-reporter.mjs'
36
- import { loadCursorIgnorePaths } from '../../../scripts/utils/load-cursor-config.mjs'
37
- import { walkDir } from '../../../scripts/utils/walkDir.mjs'
33
+ import { getMirrorGcrHint, getFromImageToken } from '../../../../scripts/utils/docker-mirror.mjs'
34
+ import { lintDockerfileWithHadolint, posixRel } from '../../../../scripts/utils/docker-hadolint.mjs'
35
+ import { createCheckReporter } from '../../../../scripts/utils/check-reporter.mjs'
36
+ import { loadCursorIgnorePaths } from '../../../../scripts/utils/load-cursor-config.mjs'
37
+ import { walkDir } from '../../../../scripts/utils/walkDir.mjs'
38
38
 
39
39
  const NEWLINE_RE = /\r?\n/
40
40
  const BUN_INSTALL_RE = /\bbun\s+(?:install|i)\b/iu
@@ -22,7 +22,7 @@
22
22
  import { spawnSync } from 'node:child_process'
23
23
  import { platform } from 'node:process'
24
24
 
25
- import { check as checkGa } from './check.mjs'
25
+ import { check as checkGa } from './workflows/check.mjs'
26
26
  import { resolveCmd } from '../../../scripts/utils/resolve-cmd.mjs'
27
27
 
28
28
  /**
@@ -19,10 +19,10 @@ import { readdir, readFile } from 'node:fs/promises'
19
19
  import { execFileSync } from 'node:child_process'
20
20
  import { join } from 'node:path'
21
21
 
22
- import { createCheckReporter } from '../../../scripts/utils/check-reporter.mjs'
23
- import { eventPathsIncludeExact, parseWorkflowYaml } from '../../../scripts/utils/gha-workflow.mjs'
24
- import { resolveCmd } from '../../../scripts/utils/resolve-cmd.mjs'
25
- import { runConftestBatch } from '../../../scripts/utils/run-conftest-batch.mjs'
22
+ import { createCheckReporter } from '../../../../scripts/utils/check-reporter.mjs'
23
+ import { eventPathsIncludeExact, parseWorkflowYaml } from '../../../../scripts/utils/gha-workflow.mjs'
24
+ import { resolveCmd } from '../../../../scripts/utils/resolve-cmd.mjs'
25
+ import { runConftestBatch } from '../../../../scripts/utils/run-conftest-batch.mjs'
26
26
 
27
27
  /** Шаблони наявності MegaLinter у вмісті workflow */
28
28
  const MEGALINTER_USE_PATTERNS = [/oxsecurity\/megalinter-action/i, /megalinter\/megalinter/i]
@@ -10,15 +10,15 @@ import { existsSync } from 'node:fs'
10
10
  import { readFile } from 'node:fs/promises'
11
11
  import { relative } from 'node:path'
12
12
 
13
- import { createCheckReporter } from '../../../scripts/utils/check-reporter.mjs'
13
+ import { createCheckReporter } from '../../../../scripts/utils/check-reporter.mjs'
14
14
  import {
15
15
  isGqlScanSourceFile,
16
16
  shouldSkipFileForGqlScan,
17
17
  sourceFileHasGqlTaggedTemplate
18
- } from '../../../scripts/utils/graphql-gql-scan.mjs'
19
- import { loadCursorIgnorePaths } from '../../../scripts/utils/load-cursor-config.mjs'
20
- import { runConftestBatch } from '../../../scripts/utils/run-conftest-batch.mjs'
21
- import { walkDir } from '../../../scripts/utils/walkDir.mjs'
18
+ } from '../../../../scripts/utils/graphql-gql-scan.mjs'
19
+ import { loadCursorIgnorePaths } from '../../../../scripts/utils/load-cursor-config.mjs'
20
+ import { runConftestBatch } from '../../../../scripts/utils/run-conftest-batch.mjs'
21
+ import { walkDir } from '../../../../scripts/utils/walkDir.mjs'
22
22
 
23
23
  /** Очікуваний файл GraphQL Config у корені (graphql.mdc). */
24
24
  export const GRAPHQL_RC_FILENAME = '.graphqlrc.yml'
@@ -27,10 +27,10 @@ import { basename, join, relative } from 'node:path'
27
27
 
28
28
  import { parseAllDocuments } from 'yaml'
29
29
 
30
- import { getRepositoryUrl } from '../../../scripts/auto-rules.mjs'
31
- import { createCheckReporter } from '../../../scripts/utils/check-reporter.mjs'
32
- import { loadCursorIgnorePaths } from '../../../scripts/utils/load-cursor-config.mjs'
33
- import { walkDir } from '../../../scripts/utils/walkDir.mjs'
30
+ import { getRepositoryUrl } from '../../../../scripts/auto-rules.mjs'
31
+ import { createCheckReporter } from '../../../../scripts/utils/check-reporter.mjs'
32
+ import { loadCursorIgnorePaths } from '../../../../scripts/utils/load-cursor-config.mjs'
33
+ import { walkDir } from '../../../../scripts/utils/walkDir.mjs'
34
34
 
35
35
  const NITRA_REPOSITORY_URL_MARKER = 'https://github.com/nitra/'
36
36
  const ABIE_REPOSITORY_URL_MARKER = 'https://github.com/abinbevefes/'
@@ -25,11 +25,11 @@ import { join, relative } from 'node:path'
25
25
  import { spawnSync } from 'node:child_process'
26
26
  import { env } from 'node:process'
27
27
 
28
- import { createCheckReporter } from '../../../scripts/utils/check-reporter.mjs'
29
- import { loadCursorIgnorePaths } from '../../../scripts/utils/load-cursor-config.mjs'
30
- import { resolveCmd } from '../../../scripts/utils/resolve-cmd.mjs'
31
- import { walkDir } from '../../../scripts/utils/walkDir.mjs'
32
- import { getMonorepoPackageRootDirs } from '../../../scripts/utils/workspaces.mjs'
28
+ import { createCheckReporter } from '../../../../scripts/utils/check-reporter.mjs'
29
+ import { loadCursorIgnorePaths } from '../../../../scripts/utils/load-cursor-config.mjs'
30
+ import { resolveCmd } from '../../../../scripts/utils/resolve-cmd.mjs'
31
+ import { walkDir } from '../../../../scripts/utils/walkDir.mjs'
32
+ import { getMonorepoPackageRootDirs } from '../../../../scripts/utils/workspaces.mjs'
33
33
 
34
34
  /** Імʼя CLI-пакета, який генерує AVIF. */
35
35
  const MINIFY_PACKAGE_NAME = '@nitra/minify-image'
@@ -19,7 +19,7 @@
19
19
  import { existsSync } from 'node:fs'
20
20
  import { readFile } from 'node:fs/promises'
21
21
 
22
- import { createCheckReporter } from '../../../scripts/utils/check-reporter.mjs'
22
+ import { createCheckReporter } from '../../../../scripts/utils/check-reporter.mjs'
23
23
 
24
24
  /** Імʼя committed-кешу (sha1 + originalSize + size) у `@nitra/minify-image` ≥ 3.2.0. */
25
25
  const HASH_CACHE_FILENAME = '.n-minify-image.tsv'
@@ -25,7 +25,7 @@ import { existsSync } from 'node:fs'
25
25
  import { readFile } from 'node:fs/promises'
26
26
  import { join, relative } from 'node:path'
27
27
 
28
- import { createCheckReporter } from '../../../scripts/utils/check-reporter.mjs'
28
+ import { createCheckReporter } from '../../../../scripts/utils/check-reporter.mjs'
29
29
  import {
30
30
  findBunSqlPerRequestConnectionInText,
31
31
  findBunSqlPgLeftoverCallInText,
@@ -36,10 +36,10 @@ import {
36
36
  findUnsafeBunSqlInListMissingEmptyGuardInText,
37
37
  isBunSqlScanSourceFile,
38
38
  textHasBunSqlImport
39
- } from '../../../scripts/utils/bun-sql-scan.mjs'
40
- import { findAllPackageJsonPaths } from '../../../scripts/utils/find-package-json-paths.mjs'
41
- import { loadCursorIgnorePaths } from '../../../scripts/utils/load-cursor-config.mjs'
42
- import { walkDir } from '../../../scripts/utils/walkDir.mjs'
39
+ } from '../../../../scripts/utils/bun-sql-scan.mjs'
40
+ import { findAllPackageJsonPaths } from '../../../../scripts/utils/find-package-json-paths.mjs'
41
+ import { loadCursorIgnorePaths } from '../../../../scripts/utils/load-cursor-config.mjs'
42
+ import { walkDir } from '../../../../scripts/utils/walkDir.mjs'
43
43
 
44
44
  /**
45
45
  * Збирає абсолютні шляхи JS/TS джерел у репозиторії для скану Bun SQL патернів.
@@ -14,10 +14,10 @@ import { existsSync } from 'node:fs'
14
14
  import { readFile } from 'node:fs/promises'
15
15
  import { join, relative } from 'node:path'
16
16
 
17
- import { createCheckReporter } from '../../../scripts/utils/check-reporter.mjs'
18
- import { loadCursorIgnorePaths } from '../../../scripts/utils/load-cursor-config.mjs'
19
- import { findRedisImportsInText, isRedisScanSourceFile, shouldSkipFileForRedisScan } from '../../../scripts/utils/redis-imports.mjs'
20
- import { walkDir } from '../../../scripts/utils/walkDir.mjs'
17
+ import { createCheckReporter } from '../../../../scripts/utils/check-reporter.mjs'
18
+ import { loadCursorIgnorePaths } from '../../../../scripts/utils/load-cursor-config.mjs'
19
+ import { findRedisImportsInText, isRedisScanSourceFile, shouldSkipFileForRedisScan } from '../../../../scripts/utils/redis-imports.mjs'
20
+ import { walkDir } from '../../../../scripts/utils/walkDir.mjs'
21
21
 
22
22
  /**
23
23
  * Збирає абсолютні шляхи JS/TS джерел у репозиторії для скану заборонених redis-імпортів.
@@ -16,17 +16,31 @@ import { copyFile, readFile } from 'node:fs/promises'
16
16
  import { dirname, join } from 'node:path'
17
17
  import { fileURLToPath } from 'node:url'
18
18
 
19
- import { createCheckReporter } from '../../../scripts/utils/check-reporter.mjs'
19
+ import { createCheckReporter } from '../../../../scripts/utils/check-reporter.mjs'
20
20
 
21
21
  /** Шлях до канонічного oxlint JSON у цьому пакеті (для перевірки та тестів). */
22
22
  export const OXLINT_CANONICAL_JSON_PATH = join(
23
23
  dirname(fileURLToPath(import.meta.url)),
24
+ '..',
25
+ '..',
26
+ '..',
27
+ '..',
28
+ 'scripts',
24
29
  'utils',
25
30
  'oxlint-canonical.json'
26
31
  )
27
32
 
28
33
  /** Шлях до канонічного knip JSON у цьому пакеті — копіюється у корінь проєкту-споживача, якщо відсутній. */
29
- export const KNIP_CANONICAL_JSON_PATH = join(dirname(fileURLToPath(import.meta.url)), 'utils', 'knip-canonical.json')
34
+ export const KNIP_CANONICAL_JSON_PATH = join(
35
+ dirname(fileURLToPath(import.meta.url)),
36
+ '..',
37
+ '..',
38
+ '..',
39
+ '..',
40
+ 'scripts',
41
+ 'utils',
42
+ 'knip-canonical.json'
43
+ )
30
44
 
31
45
  /** Мінімальні рекомендації розширень редактора з js-lint.mdc (eslint, oxlint, GA). */
32
46
  export const REQUIRED_VSCODE_EXTENSIONS = ['dbaeumer.vscode-eslint', 'github.vscode-github-actions', 'oxc.oxc-vscode']
@@ -12,8 +12,8 @@ import { existsSync } from 'node:fs'
12
12
  import { readFile } from 'node:fs/promises'
13
13
  import { join, relative } from 'node:path'
14
14
 
15
- import { createCheckReporter } from '../../../scripts/utils/check-reporter.mjs'
16
- import { findAllPackageJsonPaths } from '../../../scripts/utils/find-package-json-paths.mjs'
15
+ import { createCheckReporter } from '../../../../scripts/utils/check-reporter.mjs'
16
+ import { findAllPackageJsonPaths } from '../../../../scripts/utils/find-package-json-paths.mjs'
17
17
  import {
18
18
  findMssqlPerRequestConnectionInText,
19
19
  findSharedMssqlRequestInText,
@@ -22,9 +22,9 @@ import {
22
22
  findUnsafeMssqlInListUnparsedInText,
23
23
  findUnsafeMssqlInListMissingEmptyGuardInText,
24
24
  isMssqlScanSourceFile
25
- } from '../../../scripts/utils/mssql-pool-scan.mjs'
26
- import { loadCursorIgnorePaths } from '../../../scripts/utils/load-cursor-config.mjs'
27
- import { walkDir } from '../../../scripts/utils/walkDir.mjs'
25
+ } from '../../../../scripts/utils/mssql-pool-scan.mjs'
26
+ import { loadCursorIgnorePaths } from '../../../../scripts/utils/load-cursor-config.mjs'
27
+ import { walkDir } from '../../../../scripts/utils/walkDir.mjs'
28
28
 
29
29
  const VERSION_PREFIX_RE = /^[\^~>=<]+\s*/u
30
30
  const SEMVER_RE = /^(\d+)\.(\d+)\.(\d+)/u
@@ -37,21 +37,21 @@ import {
37
37
  findBunyanImportsInText,
38
38
  isBunyanScanSourceFile,
39
39
  shouldSkipFileForBunyanScan
40
- } from '../../../scripts/utils/bunyan-imports.mjs'
41
- import { findUncheckedProcessEnvInText, isCheckEnvScanSourceFile } from '../../../scripts/utils/check-env-scan.mjs'
42
- import { createCheckReporter } from '../../../scripts/utils/check-reporter.mjs'
43
- import { runConftestBatch } from '../../../scripts/utils/run-conftest-batch.mjs'
44
- import { findConnFileRuleViolations, isConnFileRulesSourceFile } from '../../../scripts/utils/conn-file-rules.mjs'
40
+ } from '../../../../scripts/utils/bunyan-imports.mjs'
41
+ import { findUncheckedProcessEnvInText, isCheckEnvScanSourceFile } from '../../../../scripts/utils/check-env-scan.mjs'
42
+ import { createCheckReporter } from '../../../../scripts/utils/check-reporter.mjs'
43
+ import { runConftestBatch } from '../../../../scripts/utils/run-conftest-batch.mjs'
44
+ import { findConnFileRuleViolations, isConnFileRulesSourceFile } from '../../../../scripts/utils/conn-file-rules.mjs'
45
45
  import {
46
46
  findConnFactoryImportsInText,
47
47
  isConnImportsScanSourceFile,
48
48
  isInsideConnDir,
49
49
  resolveConnDirFromPackageJson
50
- } from '../../../scripts/utils/conn-imports-scan.mjs'
51
- import { loadCursorIgnorePaths } from '../../../scripts/utils/load-cursor-config.mjs'
52
- import { findPromiseSetTimeoutInText, isPromiseSetTimeoutScanSourceFile } from '../../../scripts/utils/promise-settimeout-scan.mjs'
53
- import { walkDir } from '../../../scripts/utils/walkDir.mjs'
54
- import { getMonorepoPackageRootDirs } from '../../../scripts/utils/workspaces.mjs'
50
+ } from '../../../../scripts/utils/conn-imports-scan.mjs'
51
+ import { loadCursorIgnorePaths } from '../../../../scripts/utils/load-cursor-config.mjs'
52
+ import { findPromiseSetTimeoutInText, isPromiseSetTimeoutScanSourceFile } from '../../../../scripts/utils/promise-settimeout-scan.mjs'
53
+ import { walkDir } from '../../../../scripts/utils/walkDir.mjs'
54
+ import { getMonorepoPackageRootDirs } from '../../../../scripts/utils/workspaces.mjs'
55
55
 
56
56
  /**
57
57
  * Чи існує непорожній за змістом маркер каталогу `src/` (рекомендована структура js-run).
@@ -134,10 +134,10 @@ import { basename, dirname, join, relative, resolve } from 'node:path'
134
134
 
135
135
  import { isSeq, parseAllDocuments, parseDocument } from 'yaml'
136
136
 
137
- import { createCheckReporter } from '../../../scripts/utils/check-reporter.mjs'
138
- import { loadCursorIgnorePaths } from '../../../scripts/utils/load-cursor-config.mjs'
139
- import { runConftestBatch } from '../../../scripts/utils/run-conftest-batch.mjs'
140
- import { walkDir } from '../../../scripts/utils/walkDir.mjs'
137
+ import { createCheckReporter } from '../../../../scripts/utils/check-reporter.mjs'
138
+ import { loadCursorIgnorePaths } from '../../../../scripts/utils/load-cursor-config.mjs'
139
+ import { runConftestBatch } from '../../../../scripts/utils/run-conftest-batch.mjs'
140
+ import { walkDir } from '../../../../scripts/utils/walkDir.mjs'
141
141
 
142
142
  /** Версія набору схем yannh — узгоджено з k8s.mdc */
143
143
  const YANNH_PIN = 'v1.33.9-standalone-strict'
@@ -17,11 +17,11 @@ import { existsSync } from 'node:fs'
17
17
  import { readdir, readFile, rename, unlink, writeFile } from 'node:fs/promises'
18
18
  import { basename, dirname, join, relative } from 'node:path'
19
19
 
20
- import { findDockerfilePaths } from '../../docker/js/check.mjs'
21
- import { createCheckReporter } from '../../../scripts/utils/check-reporter.mjs'
22
- import { loadCursorIgnorePaths } from '../../../scripts/utils/load-cursor-config.mjs'
23
- import { runConftestBatch } from '../../../scripts/utils/run-conftest-batch.mjs'
24
- import { walkDir } from '../../../scripts/utils/walkDir.mjs'
20
+ import { findDockerfilePaths } from '../../../docker/js/lint/check.mjs'
21
+ import { createCheckReporter } from '../../../../scripts/utils/check-reporter.mjs'
22
+ import { loadCursorIgnorePaths } from '../../../../scripts/utils/load-cursor-config.mjs'
23
+ import { runConftestBatch } from '../../../../scripts/utils/run-conftest-batch.mjs'
24
+ import { walkDir } from '../../../../scripts/utils/walkDir.mjs'
25
25
 
26
26
  const LINE_SPLIT_RE = /\r?\n/u
27
27
  const INI_KEY_RE = /^([A-Za-z_]\w*)\s*=/u
@@ -32,10 +32,10 @@ import { promisify } from 'node:util'
32
32
 
33
33
  import { parseSync } from 'oxc-parser'
34
34
 
35
- import { dynamicImportModule, langFromPath, requireCallModule, walkAstWithAncestors } from '../../../scripts/utils/ast-scan-utils.mjs'
36
- import { createCheckReporter } from '../../../scripts/utils/check-reporter.mjs'
37
- import { loadCursorIgnorePaths } from '../../../scripts/utils/load-cursor-config.mjs'
38
- import { walkDir } from '../../../scripts/utils/walkDir.mjs'
35
+ import { dynamicImportModule, langFromPath, requireCallModule, walkAstWithAncestors } from '../../../../scripts/utils/ast-scan-utils.mjs'
36
+ import { createCheckReporter } from '../../../../scripts/utils/check-reporter.mjs'
37
+ import { loadCursorIgnorePaths } from '../../../../scripts/utils/load-cursor-config.mjs'
38
+ import { walkDir } from '../../../../scripts/utils/walkDir.mjs'
39
39
 
40
40
  const execFileAsync = promisify(execFile)
41
41
 
@@ -11,7 +11,7 @@
11
11
  */
12
12
  import { existsSync } from 'node:fs'
13
13
 
14
- import { createCheckReporter } from '../../../scripts/utils/check-reporter.mjs'
14
+ import { createCheckReporter } from '../../../../scripts/utils/check-reporter.mjs'
15
15
 
16
16
  /**
17
17
  * Перевіряє відповідність проєкту правилам php.mdc.
@@ -19,7 +19,7 @@
19
19
  import { existsSync } from 'node:fs'
20
20
  import { readFile } from 'node:fs/promises'
21
21
 
22
- import { createCheckReporter } from '../../../scripts/utils/check-reporter.mjs'
22
+ import { createCheckReporter } from '../../../../scripts/utils/check-reporter.mjs'
23
23
 
24
24
  /**
25
25
  * Альтернатива полю `stylelint` у `package.json` — зовнішній файл конфігу. Якщо
@@ -18,8 +18,8 @@
18
18
  import { existsSync, statSync } from 'node:fs'
19
19
  import { readFile } from 'node:fs/promises'
20
20
 
21
- import { createCheckReporter } from '../../../scripts/utils/check-reporter.mjs'
22
- import { runConftestBatch } from '../../../scripts/utils/run-conftest-batch.mjs'
21
+ import { createCheckReporter } from '../../../../scripts/utils/check-reporter.mjs'
22
+ import { runConftestBatch } from '../../../../scripts/utils/run-conftest-batch.mjs'
23
23
 
24
24
  /**
25
25
  * Чи є префікс `@tauri-apps/` у ключах `dependencies` або `devDependencies`.
@@ -32,8 +32,8 @@
32
32
  import { existsSync } from 'node:fs'
33
33
  import { readFile } from 'node:fs/promises'
34
34
 
35
- import { createCheckReporter } from '../../../scripts/utils/check-reporter.mjs'
36
- import { anyRunStepIncludes, parseWorkflowYaml } from '../../../scripts/utils/gha-workflow.mjs'
35
+ import { createCheckReporter } from '../../../../scripts/utils/check-reporter.mjs'
36
+ import { anyRunStepIncludes, parseWorkflowYaml } from '../../../../scripts/utils/gha-workflow.mjs'
37
37
 
38
38
  /** Заголовок абзацу про апостроф у text.mdc / n-text.mdc. */
39
39
  const UK_APOSTROPHE_HEADING = '**Український апостроф:**'
@@ -21,16 +21,16 @@ import { existsSync } from 'node:fs'
21
21
  import { readFile } from 'node:fs/promises'
22
22
  import { join, relative } from 'node:path'
23
23
 
24
- import { createCheckReporter } from '../../../scripts/utils/check-reporter.mjs'
24
+ import { createCheckReporter } from '../../../../scripts/utils/check-reporter.mjs'
25
25
  import {
26
26
  findForbiddenNodeImportsInVueFile,
27
27
  findForbiddenVueImportsInSourceFile,
28
28
  isVueImportScanSourceFile,
29
29
  shouldSkipFileForVueImportScan
30
- } from '../../../scripts/utils/vue-forbidden-imports.mjs'
31
- import { loadCursorIgnorePaths } from '../../../scripts/utils/load-cursor-config.mjs'
32
- import { walkDir } from '../../../scripts/utils/walkDir.mjs'
33
- import { getMonorepoPackageRootDirs } from '../../../scripts/utils/workspaces.mjs'
30
+ } from '../../../../scripts/utils/vue-forbidden-imports.mjs'
31
+ import { loadCursorIgnorePaths } from '../../../../scripts/utils/load-cursor-config.mjs'
32
+ import { walkDir } from '../../../../scripts/utils/walkDir.mjs'
33
+ import { getMonorepoPackageRootDirs } from '../../../../scripts/utils/workspaces.mjs'
34
34
 
35
35
  const ESBUILD_RE = /\besbuild\b/
36
36
 
@@ -2,11 +2,11 @@
2
2
  * Discovery rules для CLI `check`. Шукає правила, для яких є щось «прогонне»:
3
3
  * - JS concerns: `rules/<id>/js/<concern>/<check.mjs | check-*.mjs>` — кожен concern окремий вузол.
4
4
  * - Policy concerns: `rules/<id>/policy/<concern>/target.json` — пара з `<concern>.rego`.
5
- * - Legacy JS (на час міграції): `rules/<id>/js/check.mjs` (плаский) — мапиться у concern `legacy`,
6
- * щоб не ламати ще не мігровані правила.
7
5
  *
8
6
  * Каталог `utils/` всередині `js/` свідомо пропускається — це хелпери, не концерни.
9
7
  * Файли `*.test.mjs` фільтруються regex (`^check(?:-.+)?\.mjs$`).
8
+ * Top-level плаский `js/check.mjs` (legacy) більше не підтримується — усі вшиті правила
9
+ * у пакеті розпиляні на concern-структуру.
10
10
  *
11
11
  * Намеренно НЕ парсимо `target.json` тут (це робить runner). Discovery — швидкий скан структури:
12
12
  * шляхи + назви, без I/O вмісту.
@@ -20,9 +20,8 @@ const TEST_SUFFIX = '.test.mjs'
20
20
 
21
21
  /**
22
22
  * @typedef {object} JsConcern
23
- * @property {string} name імʼя концерну (`<name>` у `js/<name>/`); для legacy — `'legacy'`
23
+ * @property {string} name імʼя концерну (`<name>` у `js/<name>/`)
24
24
  * @property {string[]} files імена `check*.mjs` у концерні (відсортовані алфавітно)
25
- * @property {boolean} legacy чи це fallback на плаский `js/check.mjs`
26
25
  */
27
26
 
28
27
  /**
@@ -38,8 +37,7 @@ const TEST_SUFFIX = '.test.mjs'
38
37
  */
39
38
 
40
39
  /**
41
- * Перелічує JS-концерни одного правила: підкаталоги `js/<name>/` з принаймні одним `check*.mjs`,
42
- * плюс legacy-fallback на плаский `js/check.mjs` (без підкаталогу).
40
+ * Перелічує JS-концерни одного правила: підкаталоги `js/<name>/` з принаймні одним `check*.mjs`.
43
41
  *
44
42
  * `js/utils/` свідомо пропускається — це хелпери, а не концерни.
45
43
  * @param {string} jsDir абсолютний шлях `rules/<id>/js/`
@@ -49,7 +47,6 @@ async function listJsConcerns(jsDir) {
49
47
  if (!existsSync(jsDir)) return []
50
48
  const topLevel = await readdir(jsDir, { withFileTypes: true })
51
49
 
52
- // Перевага — нова concern-структура (`js/<concern>/check*.mjs`).
53
50
  /** @type {JsConcern[]} */
54
51
  const concerns = []
55
52
  for (const entry of topLevel) {
@@ -59,21 +56,7 @@ async function listJsConcerns(jsDir) {
59
56
  .filter(n => CHECK_FILENAME_RE.test(n) && !n.endsWith(TEST_SUFFIX))
60
57
  .toSorted((a, b) => a.localeCompare(b))
61
58
  if (files.length > 0) {
62
- concerns.push({ name: entry.name, files, legacy: false })
63
- }
64
- }
65
-
66
- // Legacy fallback — лише якщо subdir-концернів немає взагалі. Гібридні правила
67
- // (одночасно legacy check.mjs + нові концерни) трактуються як уже мігровані:
68
- // CLI запускає тільки субдиректорні концерни, flat-файл лишається для backward-compat
69
- // тестів, які імпортують `check` напряму.
70
- if (concerns.length === 0) {
71
- const flatChecks = topLevel
72
- .filter(e => e.isFile() && CHECK_FILENAME_RE.test(e.name) && !e.name.endsWith(TEST_SUFFIX))
73
- .map(e => e.name)
74
- .toSorted((a, b) => a.localeCompare(b))
75
- if (flatChecks.length > 0) {
76
- concerns.push({ name: 'legacy', files: flatChecks, legacy: true })
59
+ concerns.push({ name: entry.name, files })
77
60
  }
78
61
  }
79
62
 
@@ -6,8 +6,6 @@
6
6
  * false — друкуємо `✅ правило не застосовне` і завершуємо без подальших викликів.
7
7
  * 2. **JS-концерни** — кожен `check*.mjs` у `js/<concern>/`. Concern `applies` теж може мати
8
8
  * `check()` для друку контексту (його `applies()` уже відпрацював на кроці 1, він не повторюється).
9
- * Legacy-fallback: плаский `js/check.mjs` лежить як concern `legacy` — імпортується з кореня `js/`,
10
- * а не з підкаталога.
11
9
  * 3. **Policy-концерни** — кожен `policy/<concern>/target.json` через `runConftestBatch`.
12
10
  * Реcолвер `resolveTargetFiles` ділить cache (`walkCache`) між концернами.
13
11
  *
@@ -32,9 +30,7 @@ const APPLIES_CONCERN_NAME = 'applies'
32
30
  * @returns {string} абсолютний шлях
33
31
  */
34
32
  function resolveJsCheckPath(bundledRulesDir, ruleId, concern, fileName) {
35
- return concern.legacy
36
- ? join(bundledRulesDir, ruleId, 'js', fileName)
37
- : join(bundledRulesDir, ruleId, 'js', concern.name, fileName)
33
+ return join(bundledRulesDir, ruleId, 'js', concern.name, fileName)
38
34
  }
39
35
 
40
36
  /**