@nitra/cursor 1.13.87 → 1.14.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 (79) hide show
  1. package/CHANGELOG.md +48 -0
  2. package/bin/n-cursor.js +5 -6
  3. package/package.json +1 -1
  4. package/rules/abie/abie.mdc +8 -8
  5. package/rules/abie/js/{applies/check.mjs → applies.mjs} +2 -2
  6. package/rules/abie/js/{env_dns/check.mjs → env_dns.mjs} +3 -3
  7. package/rules/abie/js/{firebase_hosting/check.mjs → firebase_hosting.mjs} +1 -1
  8. package/rules/abie/js/{hc_pairing/check.mjs → hc_pairing.mjs} +4 -4
  9. package/rules/abie/js/{ua_http_route/check.mjs → ua_http_route.mjs} +6 -6
  10. package/rules/abie/js/{ua_node_selector/check.mjs → ua_node_selector.mjs} +5 -5
  11. package/rules/abie/policy/base_deployment_preem/base_deployment_preem.rego +2 -2
  12. package/rules/abie/policy/health_check_policy/health_check_policy.rego +2 -2
  13. package/rules/abie/policy/http_route_base/http_route_base.rego +1 -1
  14. package/rules/abie/utils/enabled.mjs +1 -1
  15. package/rules/abie/utils/k8s-tree.mjs +1 -1
  16. package/rules/adr/js/{hooks/check.mjs → hooks.mjs} +1 -1
  17. package/rules/bun/js/{layout/check.mjs → layout.mjs} +1 -1
  18. package/rules/capacitor/js/{platforms/check.mjs → platforms.mjs} +1 -1
  19. package/rules/changelog/changelog.mdc +1 -1
  20. package/rules/changelog/js/{consistency/check.mjs → consistency.mjs} +2 -2
  21. package/rules/changelog/{js/consistency → utils}/package-manifest.mjs +1 -1
  22. package/rules/docker/js/{lint/check.mjs → lint.mjs} +5 -5
  23. package/rules/docker/lint/lint.mjs +1 -1
  24. package/rules/docker/{js/lint → utils}/docker-hadolint.mjs +1 -1
  25. package/rules/feedback/feedback.mdc +1 -1
  26. package/rules/ga/js/{workflows/check.mjs → workflows.mjs} +5 -5
  27. package/rules/ga/lint/lint.mjs +1 -1
  28. package/rules/graphql/js/{tooling/check.mjs → tooling.mjs} +5 -5
  29. package/rules/hasura/js/{internal_urls/check.mjs → internal_urls.mjs} +4 -4
  30. package/rules/hasura/policy/svc_hl/svc_hl.rego +1 -1
  31. package/rules/image-avif/js/{avif_generation/check.mjs → avif_generation.mjs} +5 -5
  32. package/rules/image-compress/js/{package_setup/check.mjs → package_setup.mjs} +3 -3
  33. package/rules/js-bun-db/js/{safety/check.mjs → safety.mjs} +5 -5
  34. package/rules/js-bun-db/{js/safety → utils}/bun-sql-scan.mjs +1 -1
  35. package/rules/js-bun-redis/js/{imports/check.mjs → imports.mjs} +4 -4
  36. package/rules/js-bun-redis/policy/package_json/package_json.rego +1 -1
  37. package/rules/js-lint/js/{tooling/check.mjs → tooling.mjs} +8 -4
  38. package/rules/js-lint/js-lint.mdc +11 -1
  39. package/rules/js-lint/{js/tooling → utils}/rebuild-oxlint-canonical.mjs +2 -2
  40. package/rules/js-mssql/js/{deps/check.mjs → deps.mjs} +5 -5
  41. package/rules/js-mssql/{js/deps → utils}/mssql-pool-scan.mjs +1 -1
  42. package/rules/js-run/js/{runtime/check.mjs → runtime.mjs} +10 -10
  43. package/rules/js-run/{js/runtime → utils}/bunyan-imports.mjs +1 -1
  44. package/rules/js-run/{js/runtime → utils}/check-env-scan.mjs +1 -1
  45. package/rules/js-run/{js/runtime → utils}/conn-file-rules.mjs +1 -1
  46. package/rules/js-run/{js/runtime → utils}/conn-imports-scan.mjs +1 -1
  47. package/rules/js-run/{js/runtime → utils}/promise-settimeout-scan.mjs +1 -1
  48. package/rules/k8s/js/{manifests/check.mjs → manifests.mjs} +4 -4
  49. package/rules/k8s/k8s.mdc +1 -1
  50. package/rules/nginx-default-tpl/js/{template/check.mjs → template.mjs} +5 -5
  51. package/rules/npm-module/js/{package_structure/check.mjs → package_structure.mjs} +4 -4
  52. package/rules/php/js/{tooling/check.mjs → tooling.mjs} +1 -1
  53. package/rules/rego/js/{applies/check.mjs → applies.mjs} +3 -3
  54. package/rules/security/js/{sample_secret/check.mjs → sample_secret.mjs} +2 -2
  55. package/rules/security/js/{trufflehog/check.mjs → trufflehog.mjs} +3 -3
  56. package/rules/security/security.mdc +2 -2
  57. package/rules/style-lint/js/{tooling/check.mjs → tooling.mjs} +1 -1
  58. package/rules/tauri/js/{tooling/check.mjs → tooling.mjs} +2 -2
  59. package/rules/test/js/{location/check.mjs → location.mjs} +3 -3
  60. package/rules/text/js/{formatting/check.mjs → formatting.mjs} +2 -2
  61. package/rules/vue/js/{packages/check.mjs → packages.mjs} +5 -5
  62. package/scripts/auto-rules.mjs +3 -3
  63. package/scripts/claude-stop-hook.mjs +2 -2
  64. package/scripts/sync-claude-config.mjs +5 -4
  65. package/scripts/utils/discover-checkable-rules.mjs +20 -27
  66. package/scripts/utils/inline-template-links.mjs +1 -1
  67. package/scripts/utils/run-rule.mjs +18 -23
  68. package/scripts/utils/with-lock.mjs +24 -12
  69. package/.claude-template/commands/n-check.md +0 -11
  70. /package/rules/adr/js/{hooks/template → templates/hooks}/.gitignore.snippet +0 -0
  71. /package/rules/docker/{js/lint → utils}/docker-mirror.mjs +0 -0
  72. /package/rules/graphql/{js/tooling → utils}/graphql-gql-scan.mjs +0 -0
  73. /package/rules/js-lint/js/{tooling → data/tooling}/knip-canonical.json +0 -0
  74. /package/rules/js-lint/js/{tooling → data/tooling}/oxlint-canonical-skeleton.json +0 -0
  75. /package/rules/js-lint/js/{tooling → data/tooling}/oxlint-canonical.json +0 -0
  76. /package/rules/js-lint/js/{tooling → data/tooling}/oxlint-rules.tsv +0 -0
  77. /package/rules/k8s/js/{kubescape_exceptions/template → templates/kubescape_exceptions}/.kubescape-exceptions.json.snippet.json +0 -0
  78. /package/rules/security/js/{trufflehog/template → templates/trufflehog}/.trufflehog-exclude.snippet.txt +0 -0
  79. /package/rules/vue/{js/packages → utils}/vue-forbidden-imports.mjs +0 -0
@@ -1,10 +1,10 @@
1
1
  /**
2
- * Оркестратор одного правила під CLI `check`.
2
+ * Оркестратор одного правила під CLI `fix`.
3
3
  *
4
4
  * Послідовність (concerns у межах правила — алфавітно):
5
- * 1. **applies-гейт** з `js/applies/check.mjs`. Якщо модуль експортує `applies()` і вона повертає
5
+ * 1. **applies-гейт** з `js/applies.mjs`. Якщо модуль експортує `applies()` і вона повертає
6
6
  * false — друкуємо `✅ правило не застосовне` і завершуємо без подальших викликів.
7
- * 2. **JS-концерни** — кожен `check*.mjs` у `js/<concern>/`. Concern `applies` теж може мати
7
+ * 2. **JS-концерни** — кожен файл `js/<concern>.mjs`. Concern `applies` теж може мати
8
8
  * `check()` для друку контексту (його `applies()` уже відпрацював на кроці 1, він не повторюється).
9
9
  * 3. **Policy-концерни** — кожен `policy/<concern>/target.json` через `runConftestBatch`.
10
10
  * Резолвер `resolveTargetFiles` ділить cache (`walkCache`) між концернами.
@@ -24,32 +24,29 @@ import { resolveConcernTemplateData } from './template.mjs'
24
24
  const APPLIES_CONCERN_NAME = 'applies'
25
25
 
26
26
  /**
27
- * Обчислює абсолютний шлях до файла-check у JS-концерні: `rules/<id>/js/<concern>/<file>`.
28
- * Convention `js/` (за технологією) повернулась у 1.13.80 після короткої епохи `fix/`
29
- * (1.11.10–1.13.79) — щоб не плутати з кореневим `fix.mjs` entry-point'ом.
27
+ * Обчислює абсолютний шлях до файла-концерну: `rules/<id>/js/<concern>.mjs`.
28
+ * Flat-convention з 1.14.0 концерн = файл, не каталог.
30
29
  * @param {string} bundledRulesDir абсолютний `rules/`
31
30
  * @param {string} ruleId id правила
32
31
  * @param {import('./discover-checkable-rules.mjs').JsConcern} concern опис концерну
33
- * @param {string} fileName імʼя файла з `concern.files`
34
32
  * @returns {string} абсолютний шлях
35
33
  */
36
- function resolveJsCheckPath(bundledRulesDir, ruleId, concern, fileName) {
37
- return join(bundledRulesDir, ruleId, 'js', concern.name, fileName)
34
+ function resolveJsCheckPath(bundledRulesDir, ruleId, concern) {
35
+ return join(bundledRulesDir, ruleId, 'js', `${concern.name}.mjs`)
38
36
  }
39
37
 
40
38
  /**
41
- * Спробувати викликати applies() гейт з `js/applies/check.mjs` правила.
42
- * Гейт активний лише за наявності концерну з імʼям `applies` і експортом-функцією `applies` у його
43
- * першому check-файлі (алфавіт).
39
+ * Спробувати викликати applies() гейт з `js/applies.mjs` правила.
40
+ * Гейт активний лише за наявності концерну з імʼям `applies` і експортом-функцією `applies`.
44
41
  * @param {string} bundledRulesDir абсолютний `rules/`
45
42
  * @param {import('./discover-checkable-rules.mjs').CheckableRule} rule опис правила
46
43
  * @returns {Promise<boolean>} `true` — правило застосовне (або гейту немає); `false` — пропустити
47
44
  */
48
45
  async function evaluateAppliesGate(bundledRulesDir, rule) {
49
46
  const concern = rule.jsConcerns.find(c => c.name === APPLIES_CONCERN_NAME)
50
- if (!concern || concern.files.length === 0) return true
51
- const path = resolveJsCheckPath(bundledRulesDir, rule.id, concern, concern.files[0])
52
- // eslint-disable-next-line no-unsanitized/method -- path будується з discovered concern/file, які пройшли regex CHECK_FILENAME_RE
47
+ if (!concern) return true
48
+ const path = resolveJsCheckPath(bundledRulesDir, rule.id, concern)
49
+ // eslint-disable-next-line no-unsanitized/method -- path з discovered concern, файл з whitelist'у readdir
53
50
  const mod = await import(path)
54
51
  if (typeof mod.applies !== 'function') return true
55
52
  return Boolean(await mod.applies())
@@ -116,14 +113,12 @@ export async function runRule(rule, bundledRulesDir, walkCache) {
116
113
  let totalCode = 0
117
114
 
118
115
  for (const concern of rule.jsConcerns) {
119
- for (const fileName of concern.files) {
120
- const path = resolveJsCheckPath(bundledRulesDir, rule.id, concern, fileName)
121
- // eslint-disable-next-line no-unsanitized/method -- path будується з discovered concern/file, які пройшли regex CHECK_FILENAME_RE
122
- const mod = await import(path)
123
- if (typeof mod.check === 'function') {
124
- const code = await mod.check()
125
- if (code !== 0) totalCode = 1
126
- }
116
+ const path = resolveJsCheckPath(bundledRulesDir, rule.id, concern)
117
+ // eslint-disable-next-line no-unsanitized/method -- path з discovered concern, файл з whitelist'у readdir
118
+ const mod = await import(path)
119
+ if (typeof mod.check === 'function') {
120
+ const code = await mod.check()
121
+ if (code !== 0) totalCode = 1
127
122
  }
128
123
  }
129
124
 
@@ -5,21 +5,23 @@
5
5
  import * as fs from 'node:fs'
6
6
  import * as path from 'node:path'
7
7
  import * as os from 'node:os'
8
+ import { setTimeout as sleep } from 'node:timers/promises'
8
9
  import { worktreeFingerprint } from './worktree-fingerprint.mjs'
9
10
 
10
11
  const DEFAULTS = {
11
12
  ttl: 600_000,
12
13
  staleThreshold: 1_800_000,
13
14
  waitTimeout: 1_200_000,
14
- pollInterval: 1_500,
15
+ pollInterval: 1_500
15
16
  }
16
17
 
17
18
  function isAlive(pid) {
18
- try { process.kill(pid, 0); return true } catch { return false }
19
- }
20
-
21
- function sleep(ms) {
22
- return new Promise(r => setTimeout(r, ms))
19
+ try {
20
+ process.kill(pid, 0)
21
+ return true
22
+ } catch {
23
+ return false
24
+ }
23
25
  }
24
26
 
25
27
  function makeRelease(lockDir) {
@@ -67,18 +69,23 @@ export async function withLock(key, runFn, opts = {}) {
67
69
  }
68
70
  try {
69
71
  fs.mkdirSync(lockDir)
70
- fs.writeFileSync(ownerFile, JSON.stringify({ pid: process.pid, host: os.hostname(), startedAt: Date.now(), fingerprint }))
72
+ fs.writeFileSync(
73
+ ownerFile,
74
+ JSON.stringify({ pid: process.pid, host: os.hostname(), startedAt: Date.now(), fingerprint })
75
+ )
71
76
  locked = true
72
77
  break
73
78
  } catch (error) {
74
79
  if (error.code !== 'EEXIST') throw error
75
80
  let owner
76
- try { owner = JSON.parse(fs.readFileSync(ownerFile, 'utf8')) } catch {
81
+ try {
82
+ owner = JSON.parse(fs.readFileSync(ownerFile, 'utf8'))
83
+ } catch {
77
84
  fs.rmSync(lockDir, { recursive: true, force: true })
78
85
  continue
79
86
  }
80
- const stale = (Date.now() - owner.startedAt > staleThreshold) ||
81
- (os.hostname() === owner.host && !isAlive(owner.pid))
87
+ const stale =
88
+ Date.now() - owner.startedAt > staleThreshold || (os.hostname() === owner.host && !isAlive(owner.pid))
82
89
  if (stale) {
83
90
  console.error(`🧹 ${key}: знайдено застарілий лок — очищаю`)
84
91
  fs.rmSync(lockDir, { recursive: true, force: true })
@@ -100,9 +107,14 @@ export async function withLock(key, runFn, opts = {}) {
100
107
  release()
101
108
  return 0
102
109
  }
103
- } catch { /* result.json не існує або пошкоджений */ }
110
+ } catch {
111
+ /* result.json не існує або пошкоджений */
112
+ }
104
113
 
105
- const onSignal = () => { release(); process.exit(130) }
114
+ const onSignal = () => {
115
+ release()
116
+ process.exit(130)
117
+ }
106
118
  process.once('SIGINT', onSignal)
107
119
  process.once('SIGTERM', onSignal)
108
120
 
@@ -1,11 +0,0 @@
1
- ---
2
- description: >-
3
- Запустити всі програмні перевірки правил (`npx @nitra/cursor fix`)
4
- ---
5
-
6
- # n-check
7
-
8
- Запусти `npx @nitra/cursor fix` і пройдися по результатах.
9
-
10
- - Якщо є помилки — виправи відповідно до правила, на яке вказує перевірка.
11
- - Якщо все чисто — підтверди коротким повідомленням і переходь до наступного кроку.