@7n/rules 1.30.0 → 1.32.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 (142) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/package.json +1 -1
  3. package/rules/{style → k8s/dremio_logging}/docs/index.md +2 -4
  4. package/rules/k8s/dremio_logging/docs/main.md +31 -0
  5. package/rules/k8s/dremio_logging/dremio_logging.mdc +1 -0
  6. package/scripts/docs/upgrade-n-rules-and-install.md +2 -1
  7. package/scripts/upgrade-n-rules-and-install.mjs +86 -19
  8. package/skills/taze/js/docs/index.md +4 -6
  9. package/skills/taze/js/docs/migration-cache.md +38 -0
  10. package/skills/taze/js/docs/orchestrate.md +1 -1
  11. package/rules/style/admin_table/admin_table.mdc +0 -88
  12. package/rules/style/admin_table/concern.json +0 -7
  13. package/rules/style/admin_table/docs/index.md +0 -9
  14. package/rules/style/admin_table/docs/main.md +0 -14
  15. package/rules/style/admin_table/main.mjs +0 -46
  16. package/rules/style/colors/colors.mdc +0 -21
  17. package/rules/style/colors/concern.json +0 -3
  18. package/rules/style/gap/concern.json +0 -7
  19. package/rules/style/gap/docs/index.md +0 -9
  20. package/rules/style/gap/docs/main.md +0 -15
  21. package/rules/style/gap/gap.mdc +0 -22
  22. package/rules/style/gap/main.mjs +0 -51
  23. package/rules/style/lint/concern.json +0 -7
  24. package/rules/style/lint/docs/fix-lint.md +0 -29
  25. package/rules/style/lint/docs/index.md +0 -11
  26. package/rules/style/lint/docs/main.md +0 -29
  27. package/rules/style/lint/fix-lint.mjs +0 -66
  28. package/rules/style/lint/main.mjs +0 -68
  29. package/rules/style/main.json +0 -1
  30. package/rules/style/main.mdc +0 -12
  31. package/rules/style/package_json/concern.json +0 -9
  32. package/rules/style/package_json/docs/fix-package_json.md +0 -27
  33. package/rules/style/package_json/docs/index.md +0 -9
  34. package/rules/style/package_json/fix-package_json.mjs +0 -3
  35. package/rules/style/package_json/package_json.mdc +0 -18
  36. package/rules/style/package_json/package_json.rego +0 -31
  37. package/rules/style/package_json/template/package.json.snippet.json +0 -5
  38. package/rules/style/quasar/concern.json +0 -3
  39. package/rules/style/quasar/quasar.mdc +0 -7
  40. package/rules/style/quasar_fixes/concern.json +0 -7
  41. package/rules/style/quasar_fixes/docs/index.md +0 -9
  42. package/rules/style/quasar_fixes/docs/main.md +0 -16
  43. package/rules/style/quasar_fixes/main.mjs +0 -57
  44. package/rules/style/quasar_fixes/quasar_fixes.mdc +0 -32
  45. package/rules/style/tooling/concern.json +0 -14
  46. package/rules/style/tooling/docs/fix-tooling.md +0 -29
  47. package/rules/style/tooling/docs/index.md +0 -12
  48. package/rules/style/tooling/docs/main.md +0 -34
  49. package/rules/style/tooling/fix-tooling.mjs +0 -58
  50. package/rules/style/tooling/main.mjs +0 -73
  51. package/rules/style/tooling/tooling.mdc +0 -85
  52. package/rules/style/vscode_extensions/concern.json +0 -9
  53. package/rules/style/vscode_extensions/docs/fix-vscode_extensions.md +0 -25
  54. package/rules/style/vscode_extensions/docs/index.md +0 -11
  55. package/rules/style/vscode_extensions/fix-vscode_extensions.mjs +0 -1
  56. package/rules/style/vscode_extensions/template/extensions.json.snippet.json +0 -1
  57. package/rules/style/vscode_extensions/vscode_extensions.mdc +0 -13
  58. package/rules/style/vscode_extensions/vscode_extensions.rego +0 -13
  59. package/rules/style/vscode_settings/concern.json +0 -9
  60. package/rules/style/vscode_settings/docs/fix-vscode_settings.md +0 -27
  61. package/rules/style/vscode_settings/docs/index.md +0 -9
  62. package/rules/style/vscode_settings/fix-vscode_settings.mjs +0 -5
  63. package/rules/style/vscode_settings/template/settings.json.snippet.json +0 -5
  64. package/rules/style/vscode_settings/vscode_settings.mdc +0 -19
  65. package/rules/style/vscode_settings/vscode_settings.rego +0 -15
  66. package/rules/test/cargo_mutants_config/cargo_mutants_config.mdc +0 -18
  67. package/rules/test/cargo_mutants_config/concern.json +0 -8
  68. package/rules/test/cargo_mutants_config/data/cargo_mutants_config/mutants.toml.baseline +0 -7
  69. package/rules/test/cargo_mutants_config/docs/fix-cargo_mutants_config.md +0 -31
  70. package/rules/test/cargo_mutants_config/docs/index.md +0 -12
  71. package/rules/test/cargo_mutants_config/docs/main.md +0 -36
  72. package/rules/test/cargo_mutants_config/fix-cargo_mutants_config.mjs +0 -49
  73. package/rules/test/cargo_mutants_config/main.mjs +0 -62
  74. package/rules/test/docs/index.md +0 -11
  75. package/rules/test/lib/collect-test-file-offenders.mjs +0 -49
  76. package/rules/test/lib/docs/collect-test-file-offenders.md +0 -30
  77. package/rules/test/lib/docs/index.md +0 -9
  78. package/rules/test/location/concern.json +0 -8
  79. package/rules/test/location/docs/index.md +0 -11
  80. package/rules/test/location/docs/main.md +0 -36
  81. package/rules/test/location/location.mdc +0 -52
  82. package/rules/test/location/main.mjs +0 -70
  83. package/rules/test/main.json +0 -1
  84. package/rules/test/main.mdc +0 -26
  85. package/rules/test/no-bun-test-import/concern.json +0 -7
  86. package/rules/test/no-bun-test-import/docs/fix-no-bun-test-import.md +0 -31
  87. package/rules/test/no-bun-test-import/docs/index.md +0 -10
  88. package/rules/test/no-bun-test-import/docs/main.md +0 -36
  89. package/rules/test/no-bun-test-import/fix-no-bun-test-import.mjs +0 -51
  90. package/rules/test/no-bun-test-import/main.mjs +0 -105
  91. package/rules/test/no-bun-test-import/no-bun-test-import.mdc +0 -9
  92. package/rules/test/no-console-store-restore/concern.json +0 -7
  93. package/rules/test/no-console-store-restore/docs/index.md +0 -11
  94. package/rules/test/no-console-store-restore/docs/main.md +0 -44
  95. package/rules/test/no-console-store-restore/main.mjs +0 -55
  96. package/rules/test/no-console-store-restore/no-console-store-restore.mdc +0 -11
  97. package/rules/test/no-process-chdir/concern.json +0 -7
  98. package/rules/test/no-process-chdir/docs/index.md +0 -11
  99. package/rules/test/no-process-chdir/docs/main.md +0 -32
  100. package/rules/test/no-process-chdir/main.mjs +0 -40
  101. package/rules/test/no-process-chdir/no-process-chdir.mdc +0 -15
  102. package/rules/test/no-relative-fs-path/concern.json +0 -7
  103. package/rules/test/no-relative-fs-path/docs/index.md +0 -11
  104. package/rules/test/no-relative-fs-path/docs/main.md +0 -34
  105. package/rules/test/no-relative-fs-path/main.mjs +0 -239
  106. package/rules/test/no-relative-fs-path/no-relative-fs-path.mdc +0 -22
  107. package/rules/test/package_json/concern.json +0 -11
  108. package/rules/test/package_json/package_json.mdc +0 -18
  109. package/rules/test/package_json/package_json.rego +0 -25
  110. package/rules/test/package_json/template/package.json.contains.json +0 -6
  111. package/rules/test/sandbox-aware-test/concern.json +0 -7
  112. package/rules/test/sandbox-aware-test/docs/index.md +0 -11
  113. package/rules/test/sandbox-aware-test/docs/main.md +0 -55
  114. package/rules/test/sandbox-aware-test/main.mjs +0 -89
  115. package/rules/test/sandbox-aware-test/sandbox-aware-test.mdc +0 -28
  116. package/rules/test/stryker_config/concern.json +0 -8
  117. package/rules/test/stryker_config/data/stryker_config/docs/index.md +0 -13
  118. package/rules/test/stryker_config/data/stryker_config/docs/stryker-vue-macros-ignorer.md +0 -31
  119. package/rules/test/stryker_config/data/stryker_config/docs/stryker.config.baseline.md +0 -31
  120. package/rules/test/stryker_config/data/stryker_config/docs/stryker.config.vue.baseline.md +0 -35
  121. package/rules/test/stryker_config/data/stryker_config/stryker-vue-macros-ignorer.mjs +0 -48
  122. package/rules/test/stryker_config/data/stryker_config/stryker.config.baseline.mjs +0 -18
  123. package/rules/test/stryker_config/data/stryker_config/stryker.config.vue.baseline.mjs +0 -23
  124. package/rules/test/stryker_config/data/vitest_config/docs/index.md +0 -11
  125. package/rules/test/stryker_config/data/vitest_config/docs/vitest.config.baseline.md +0 -35
  126. package/rules/test/stryker_config/data/vitest_config/vitest.config.baseline.js +0 -22
  127. package/rules/test/stryker_config/docs/fix-stryker_config.md +0 -42
  128. package/rules/test/stryker_config/docs/index.md +0 -12
  129. package/rules/test/stryker_config/docs/main.md +0 -38
  130. package/rules/test/stryker_config/fix-stryker_config.mjs +0 -76
  131. package/rules/test/stryker_config/main.mjs +0 -504
  132. package/rules/test/stryker_config/stryker_config.mdc +0 -26
  133. package/rules/test/vitest-api-conventions/concern.json +0 -7
  134. package/rules/test/vitest-api-conventions/docs/index.md +0 -9
  135. package/rules/test/vitest-api-conventions/docs/main.md +0 -40
  136. package/rules/test/vitest-api-conventions/main.mjs +0 -153
  137. package/rules/test/vitest-api-conventions/vitest-api-conventions.mdc +0 -129
  138. package/rules/test/vitest-config-pool-forks/concern.json +0 -7
  139. package/rules/test/vitest-config-pool-forks/docs/index.md +0 -11
  140. package/rules/test/vitest-config-pool-forks/docs/main.md +0 -42
  141. package/rules/test/vitest-config-pool-forks/main.mjs +0 -41
  142. package/rules/test/vitest-config-pool-forks/vitest-config-pool-forks.mdc +0 -34
package/CHANGELOG.md CHANGED
@@ -1,5 +1,18 @@
1
1
  # Changelog
2
2
 
3
+ ## [1.32.0] - 2026-07-19
4
+
5
+ ### Changed
6
+
7
+ - lint: правило test переїхало у @7n/rules-lang-js (vitest/stryker/ізоляція тестів), а концерн cargo_mutants_config — у правило rust плагіна @7n/rules-lang-rust (семантично канон rust-тулчейну; активація за glob Cargo.toml, у rust-only репо працює без lang-js) — у ядрі 23 правила, мовних правил не лишилось
8
+
9
+ ## [1.31.0] - 2026-07-19
10
+
11
+ ### Changed
12
+
13
+ - sync: діапазони вже оголошених плагінів @7n/rules-* у package.json підіймаються до ^latest тим самим кроком, що й ядро — фікси плагінів доїжджають без ручного bun update (bun i сам по собі поважає lockfile); недоступний registry для окремого плагіна — warning і пропуск
14
+ - lint: правило style (stylelint/css/vue-стилі) переїхало з ядра у @7n/rules-lang-js — фінальний крок фази 5 spec lang-plugins-extraction по фронтенд-сімʼї
15
+
3
16
  ## [1.30.0] - 2026-07-19
4
17
 
5
18
  ### Added
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@7n/rules",
3
- "version": "1.30.0",
3
+ "version": "1.32.0",
4
4
  "description": "CLI еталонних правил і skills (префікс n-): синк у репозиторій, дельта-lint, конформність",
5
5
  "keywords": [
6
6
  "cli",
@@ -1,11 +1,9 @@
1
1
  ---
2
2
  type: Directory Index
3
- title: npm/rules/style
4
- resource: npm/rules/style/
3
+ title: npm/rules/k8s/dremio_logging
4
+ resource: npm/rules/k8s/dremio_logging/
5
5
  ---
6
6
 
7
- # npm/rules/style
8
-
9
7
  | Файл | Тип |
10
8
  | ------------------- | --------- |
11
9
  | [main.mjs](main.md) | JS Module |
@@ -0,0 +1,31 @@
1
+ ---
2
+ type: JS Module
3
+ title: main.mjs
4
+ resource: npm/rules/k8s/dremio_logging/main.mjs
5
+ docgen:
6
+ crc: a89abb0a
7
+ model: openai-codex/gpt-5.4-mini
8
+ tier: cloud-min
9
+ score: 95
10
+ issues: anchor-miss:(k8s.mdc),judge:inaccurate:0.99
11
+ judgeModel: openai-codex/gpt-5.4-mini
12
+ ---
13
+
14
+ ## Огляд
15
+
16
+ `zkLogbackRootLevelViolation` перевіряє повідомлення, пов’язані з надто гучним `root` у `k8s.mdc`, а `lint` збирає ці перевірки в один pass і повертає результат без зупинки процесу. Поведінка read-only: правило не пише у ФС чи БД, працює fail-safe й не кидає винятків назовні.
17
+
18
+ ## Поведінка
19
+
20
+ - `zkLogbackRootLevelViolation` — перевіряє, чи вбудований `logback.xml` у ZooKeeper-templated файлі не тримає `root` на надто гучному рівні; повертає текст порушення з міткою `` або `null`, якщо перевірка не потрібна або рівень уже прийнятний.
21
+ - `lint` — проходить по вказаних файлах у read-only режимі, збирає порушення для `k8s.dremio_logging` і не виводить помилки назовні; пропускає файли, які не вдалося прочитати, та позначає знайдені проблеми міткою ``.
22
+
23
+ ## Публічний API
24
+
25
+ - zkLogbackRootLevelViolation — позначає ZooKeeper Helm-темплейт, якщо вбудований `logback.xml` має занадто гучний `root`-рівень (`info`, `debug`, `trace`) або взагалі не задає `root`; не чіпає файли, де `root` уже `warn`, `error` чи `off`.
26
+ - lint — запускає `k8s.dremio_logging` для ZooKeeper-темплейтів у межах одного файлу, лише для читання.
27
+
28
+ ## Гарантії поведінки
29
+
30
+ - Read-only: не виконує операцій запису (ФС/БД).
31
+ - Перехоплює помилки і не пропускає винятків назовні (fail-safe).
@@ -39,6 +39,7 @@ JS-детектор (не rego): `main.mjs`, `lint(ctx)`, per-file, glob `**/dre
39
39
  **Що перевіряється:** якщо файл визначає `ConfigMap` з `data["logback.xml"]` (bundled-конфіг образу `zookeeper:3.8.4-jre-17`, монтується поверх `/conf/logback.xml`), його `<root level="...">` має бути `warn`/`error`/`off` (case-insensitive) — не `info`/`debug`/`trace` (дефолт бандлованого файлу) і не відсутній.
40
40
 
41
41
  **Чому:** readiness/liveness `ruok`-проби виконуються кожні ~10s на кожен zk-под; `NIOServerCnxn` логує це на INFO незалежно від навантаження. Керувати рівнем ззовні НЕ вдається для цього образу:
42
+
42
43
  - `ZOO_LOG4J_PROP` — змінна Bitnami-образів, тут взагалі не читається жодним скриптом.
43
44
  - `-Dzookeeper.console.threshold=WARN` через `JVMFLAGS` — перебивається `<property name="zookeeper.console.threshold" value="INFO"/>` у бандлованому файлі.
44
45
 
@@ -3,7 +3,7 @@ type: JS Module
3
3
  title: upgrade-n-rules-and-install.mjs
4
4
  resource: npm/scripts/upgrade-n-rules-and-install.mjs
5
5
  docgen:
6
- crc: f33841b9
6
+ crc: ab3a4cc2
7
7
  model: omlx/gemma-4-e4b-it-OptiQ-4bit
8
8
  score: 100
9
9
  issues: judge:inaccurate:0.98
@@ -28,6 +28,7 @@ shouldSkipNpmVersionUpgrade — Визначає, чи можна замінит
28
28
  fetchLatestNRulesVersionFromNpm — Отримує актуальну версію пакета `@7n/rules` з реєстру npm (через поле `version` у JSON dist-tag `latest`), що доступно на https://registry.npmjs.org/@7n/rules/latest.
29
29
  resolveInstalledPackageRoot — Знаходить абсолютний шлях до встановленого пакета у директорії `node_modules`, або надає резервний шлях.
30
30
  upgradeNRulesToLatestAndBunInstall — Оновлює `@7n/rules` до останньої версії з npm (якщо це дозволено конфігурацією), виконує встановлення залежностей за допомогою `bun i`, і повертає корінь пакета для подальшої синхронізації конфігураційних файлів, таких як `mdc/`.
31
+ upgradePluginRanges — Підіймає діапазони вже оголошених плагінів `@7n/rules-*` у dependencies/devDependencies до `^latest` з npm (мутує pkg; той самий крок, що й для ядра — бо `bun i` поважає lockfile і фікси плагінів інакше не доїжджають). Специфікатори поза npm-semver (workspace:, file:, git…) не чіпає; недоступний registry для окремого плагіна — warning і пропуск.
31
32
 
32
33
  ## Гарантії поведінки
33
34
 
@@ -22,6 +22,11 @@ const PACKAGE_NAME = '@7n/rules'
22
22
  const LEGACY_PACKAGE_NAME = '@nitra/cursor'
23
23
  const NPM_LATEST_URL = 'https://registry.npmjs.org/@7n/rules/latest'
24
24
 
25
+ // Плагіни екосистеми (@7n/rules-lang-js, -ci-github, …) — їх діапазони sync
26
+ // підіймає до ^latest тим самим механізмом, що й ядро: `bun i` сам по собі
27
+ // поважає lockfile, і фікси плагінів навіть у межах діапазону не доїжджали б.
28
+ const PLUGIN_NAME_RE = /^@7n\/rules-/
29
+
25
30
  const execFileAsync = promisify(execFile)
26
31
 
27
32
  const WORKSPACE_RE = /^workspace:/i
@@ -67,23 +72,71 @@ export function shouldSkipNpmVersionUpgrade(specifier) {
67
72
  }
68
73
 
69
74
  /**
70
- * Остання версія пакета з npm (поле `version` у JSON dist-tag `latest`).
75
+ * Остання версія довільного пакета з npm (поле `version` у dist-tag `latest`).
76
+ * @param {string} packageName npm-ім'я пакета
71
77
  * @returns {Promise<string>} semver без префікса `^`
72
78
  */
73
- export async function fetchLatestNRulesVersionFromNpm() {
74
- const res = await fetch(NPM_LATEST_URL, {
79
+ async function fetchLatestVersionFromNpm(packageName) {
80
+ const url = packageName === PACKAGE_NAME ? NPM_LATEST_URL : `https://registry.npmjs.org/${packageName}/latest`
81
+ const res = await fetch(url, {
75
82
  headers: { accept: 'application/json' }
76
83
  })
77
84
  if (!res.ok) {
78
- throw new Error(`npm registry: ${res.status} ${res.statusText} для ${PACKAGE_NAME}`)
85
+ throw new Error(`npm registry: ${res.status} ${res.statusText} для ${packageName}`)
79
86
  }
80
87
  const data = await res.json()
81
88
  if (!data || typeof data.version !== 'string' || !data.version.trim()) {
82
- throw new Error(`npm registry: у відповіді для ${PACKAGE_NAME} немає поля version`)
89
+ throw new Error(`npm registry: у відповіді для ${packageName} немає поля version`)
83
90
  }
84
91
  return data.version.trim()
85
92
  }
86
93
 
94
+ /**
95
+ * Остання версія пакета `@7n/rules` з npm.
96
+ * @returns {Promise<string>} semver без префікса `^`
97
+ */
98
+ export async function fetchLatestNRulesVersionFromNpm() {
99
+ return await fetchLatestVersionFromNpm(PACKAGE_NAME)
100
+ }
101
+
102
+ /**
103
+ * Підіймає діапазони встановлених плагінів `@7n/rules-*` у package.json до
104
+ * `^latest` з npm (мутує `pkg`). Специфікатори поза npm-semver
105
+ * (`workspace:`, `file:`, git тощо) не чіпає; недоступний registry для
106
+ * окремого плагіна — warning і пропуск (sync не має падати без мережі).
107
+ * @param {{ dependencies?: Record<string, string>, devDependencies?: Record<string, string> }} pkg розпарсений package.json проєкту
108
+ * @returns {Promise<string[]>} імена плагінів, чиї діапазони змінено
109
+ */
110
+ export async function upgradePluginRanges(pkg) {
111
+ /** @type {Array<{ section: 'dependencies' | 'devDependencies', name: string, value: string }>} */
112
+ const candidates = []
113
+ for (const section of /** @type {const} */ (['dependencies', 'devDependencies'])) {
114
+ const deps = pkg[section]
115
+ if (!deps || typeof deps !== 'object' || Array.isArray(deps)) continue
116
+ for (const [name, value] of Object.entries(deps)) {
117
+ if (PLUGIN_NAME_RE.test(name) && typeof value === 'string' && !shouldSkipNpmVersionUpgrade(value)) {
118
+ candidates.push({ section, name, value })
119
+ }
120
+ }
121
+ }
122
+ const changed = []
123
+ const latests = await Promise.allSettled(candidates.map(c => fetchLatestVersionFromNpm(c.name)))
124
+ for (const [i, settled] of latests.entries()) {
125
+ const { section, name, value } = candidates[i]
126
+ if (settled.status === 'rejected') {
127
+ console.warn(`⚠️ ${name}: npm registry недоступний (${settled.reason?.message ?? settled.reason}) — пропускаю\n`)
128
+ continue
129
+ }
130
+ const desired = `^${settled.value}`
131
+ if (value !== desired) {
132
+ pkg[section][name] = desired
133
+ changed.push(name)
134
+ console.log(`⬆️ Оновлено ${name} ${value} → ${desired} у ${section}\n`)
135
+ }
136
+ }
137
+ return changed
138
+ }
139
+
87
140
  /**
88
141
  * Версія з package.json вказаного кореня пакету (fallback, коли registry недоступний).
89
142
  * @param {string} packageRoot корінь пакету поточного процесу CLI
@@ -113,6 +166,25 @@ export function resolveInstalledPackageRoot(projectRoot, fallbackPackageRoot, pa
113
166
  return fallbackPackageRoot
114
167
  }
115
168
 
169
+ /**
170
+ * Остання версія ядра з npm; коли registry недоступний (або до першої
171
+ * публікації — 404) — fallback на версію пакету поточного процесу.
172
+ * @param {string} fallbackPackageRoot корінь пакету з поточного процесу CLI
173
+ * @returns {Promise<string>} semver без префікса `^`
174
+ */
175
+ async function resolveLatestCoreVersion(fallbackPackageRoot) {
176
+ try {
177
+ return await fetchLatestNRulesVersionFromNpm()
178
+ } catch (error) {
179
+ const bundled = await readPackageVersionSafe(fallbackPackageRoot)
180
+ if (!bundled) {
181
+ throw error
182
+ }
183
+ console.log(`⚠️ npm registry недоступний для ${PACKAGE_NAME} — використовую bundled-версію ${bundled}\n`)
184
+ return bundled
185
+ }
186
+ }
187
+
116
188
  /**
117
189
  * Запускає `bun i` у вказаному каталозі з виводом у поточний stdio.
118
190
  * @param {string} projectRoot cwd для процесу
@@ -221,18 +293,11 @@ export async function upgradeNRulesToLatestAndBunInstall(projectRoot, fallbackPa
221
293
  return resolveInstalledPackageRoot(projectRoot, fallbackPackageRoot)
222
294
  }
223
295
 
224
- let latest
225
- try {
226
- latest = await fetchLatestNRulesVersionFromNpm()
227
- } catch (error) {
228
- // До першої публікації @7n/rules registry віддає 404 — fallback на версію пакету поточного процесу
229
- latest = await readPackageVersionSafe(fallbackPackageRoot)
230
- if (!latest) {
231
- throw error
232
- }
233
- console.log(`⚠️ npm registry недоступний для ${PACKAGE_NAME} — використовую bundled-версію ${latest}\n`)
234
- }
235
- const desired = `^${latest}`
296
+ const desired = `^${await resolveLatestCoreVersion(fallbackPackageRoot)}`
297
+
298
+ // Діапазони вже оголошених плагінів @7n/rules-* — до ^latest тим самим
299
+ // кроком (мутує pkg; запис на диск — разом із записом по ядру нижче).
300
+ const upgradedPlugins = await upgradePluginRanges(pkg)
236
301
 
237
302
  if (!found) {
238
303
  if (!pkg.devDependencies || typeof pkg.devDependencies !== 'object' || Array.isArray(pkg.devDependencies)) {
@@ -246,7 +311,7 @@ export async function upgradeNRulesToLatestAndBunInstall(projectRoot, fallbackPa
246
311
  return resolveInstalledPackageRoot(projectRoot, fallbackPackageRoot)
247
312
  }
248
313
 
249
- if (found.value === desired) {
314
+ if (found.value === desired && upgradedPlugins.length === 0) {
250
315
  console.log(`📌 ${PACKAGE_NAME} уже ${desired} у package.json — виконуємо bun i\n`)
251
316
  } else {
252
317
  if (found.section === 'devDependencies') {
@@ -255,7 +320,9 @@ export async function upgradeNRulesToLatestAndBunInstall(projectRoot, fallbackPa
255
320
  pkg.dependencies[PACKAGE_NAME] = desired
256
321
  }
257
322
  await writeFile(pkgPath, `${JSON.stringify(pkg, null, 2)}\n`, 'utf8')
258
- console.log(`📝 Оновлено ${PACKAGE_NAME} → ${desired} у package.json\n`)
323
+ if (found.value !== desired) {
324
+ console.log(`📝 Оновлено ${PACKAGE_NAME} → ${desired} у package.json\n`)
325
+ }
259
326
  }
260
327
 
261
328
  await runBunInstall(projectRoot)
@@ -4,9 +4,7 @@ title: npm/skills/taze/js
4
4
  resource: npm/skills/taze/js/
5
5
  ---
6
6
 
7
- | Файл | Тип |
8
- | ------------------------------------- | --------- |
9
- | [cargo-diff.mjs](cargo-diff.md) | JS Module |
10
- | [diff.mjs](diff.md) | JS Module |
11
- | [orchestrate.mjs](orchestrate.md) | JS Module |
12
- | [rust-provider.mjs](rust-provider.md) | JS Module |
7
+ | Файл | Тип |
8
+ | ----------------------------------------- | --------- |
9
+ | [migration-cache.mjs](migration-cache.md) | JS Module |
10
+ | [orchestrate.mjs](orchestrate.md) | JS Module |
@@ -0,0 +1,38 @@
1
+ ---
2
+ type: JS Module
3
+ title: migration-cache.mjs
4
+ resource: npm/skills/taze/js/migration-cache.mjs
5
+ docgen:
6
+ crc: 5f264929
7
+ model: openai-codex/gpt-5.4-mini
8
+ tier: cloud-min
9
+ score: 100
10
+ issues: judge:inaccurate:0.98
11
+ judgeModel: openai-codex/gpt-5.4-mini
12
+ ---
13
+
14
+ ## Огляд
15
+
16
+ Модуль надає `DEFAULT_CACHE_DIR`, `migrationCacheKey`, `readMigrationCache`, `writeMigrationCache` і `withKnownMigrationNotes` для роботи з локальним кешем відомих результатів аналізу міграцій у межах прогону. Він зберігає та повторно читає вже відомі записи, а `withKnownMigrationNotes` підставляє їх у промпт, щоб не повторювати дослідження там, де результат уже є. Модуль fail-safe: не кидає винятків назовні й за окремих помилок повертає порожнє значення, зокрема `null`.
17
+
18
+ ## Поведінка
19
+
20
+ - `DEFAULT_CACHE_DIR` — стандартний спільний каталог для кешу міграцій на цій машині, щоб різні репозиторії могли повторно використовувати вже відомі результати.
21
+ - `migrationCacheKey` — перетворює назву пакета і діапазон версій на стабільний безпечний ключ для кешу.
22
+ - `readMigrationCache` — читає кешований запис міграції для потрібної пари версій; якщо запису немає або він пошкоджений, мовчки повертає `null`.
23
+ - `writeMigrationCache` — зберігає результат аналізу міграції в кеш, щоб наступні запуски на цій машині могли його повторити без нового дослідження.
24
+ - `withKnownMigrationNotes` — додає до промпта підсумок уже відомої міграції з кешу й підказує пропустити повторне дослідження та перейти до перевірки використання в поточному проєкті.
25
+
26
+ ## Публічний API
27
+
28
+ - DEFAULT_CACHE_DIR — Спільний каталог кешу міграцій для всіх репозиторіїв на цій машині; не прив’язаний до конкретного worktree.
29
+ - migrationCacheKey — Перетворює `` на безпечне ім’я файлу для спільного кешу між репо.
30
+ - readMigrationCache — Повертає збережений запис міграції для ``, якщо його вже обробляли в іншому repo/worktree; відсутній або пошкоджений запис дає `null`.
31
+ - writeMigrationCache — Записує результат LLM-обробки для ``, щоб не повторювати дослідження changelog для такого ж bump-а.
32
+ - withKnownMigrationNotes — Додає до prompt короткий підсумок знайденої міграції і, якщо є кеш, пропускає дослідження changelog/diff на користь пошуку використання в поточному проєкті.
33
+
34
+ ## Гарантії поведінки
35
+
36
+ - Перехоплює помилки і не пропускає винятків назовні (fail-safe).
37
+ - За певних помилок повертає порожнє значення (напр. `null`) замість винятку.
38
+ - Кешує результати в межах одного прогону.
@@ -3,7 +3,7 @@ type: JS Module
3
3
  title: orchestrate.mjs
4
4
  resource: npm/skills/taze/js/orchestrate.mjs
5
5
  docgen:
6
- crc: 9e3842cb
6
+ crc: 7bf5d0c0
7
7
  model: openai-codex/gpt-5.4-mini
8
8
  score: 100
9
9
  issues: judge:inaccurate:0.98
@@ -1,88 +0,0 @@
1
- ## Адмінські таблиці — n-admin-table
2
-
3
- Для таблиць, що мають займати всю висоту сторінки (або блоку), додавай клас `n-admin-table` і атрибути `hide-no-data`, `dense`, `flat`. Таблиця автоматично розтягнеться на весь доступний простір. У блоках меншої висоти — задай їм явний `height`.
4
-
5
- ```vue
6
- <!-- ТАБЛИЦЯ -->
7
- <q-table class="n-admin-table" hide-no-data flat dense />
8
- ```
9
-
10
- Якщо клас `.n-admin-table` не визначено в `app.scss` — додай:
11
-
12
- ```scss
13
- // ADMIN TABLE
14
- .n-admin-table {
15
- height: calc(100vh - 106px);
16
-
17
- thead {
18
- position: sticky;
19
- z-index: 3;
20
- top: 0;
21
-
22
- tr th {
23
- background-color: $grey-3;
24
- height: 36px !important;
25
- }
26
- }
27
-
28
- // tbody td {
29
- // font-size: 14px;
30
- // }
31
-
32
- tbody tr:last-child td {
33
- border-bottom: 1px solid rgb(0 0 0 / 12%) !important;
34
- }
35
-
36
- th:first-child,
37
- td:first-child,
38
- th:last-child,
39
- td:last-child {
40
- width: 1px;
41
- white-space: nowrap;
42
- }
43
-
44
- .q-table__bottom {
45
- background-color: $grey-3;
46
- }
47
-
48
- .q-table__progress th {
49
- height: 1px !important;
50
- }
51
-
52
- .text-wrap {
53
- max-width: 250px;
54
- white-space: normal;
55
- }
56
-
57
- // sticky columns
58
- td.sticky-left {
59
- position: sticky;
60
- left: 0;
61
- z-index: 2;
62
- background-color: white;
63
- box-shadow: 2px 0 5px #0002;
64
- }
65
-
66
- td.sticky-right {
67
- position: sticky;
68
- right: 0;
69
- z-index: 2;
70
- background-color: white;
71
- box-shadow: -2px 0 5px #0002;
72
- }
73
-
74
- th.sticky-left {
75
- position: sticky;
76
- left: 0;
77
- z-index: 3;
78
- box-shadow: 2px 0 5px #0002;
79
- }
80
-
81
- th.sticky-right {
82
- position: sticky;
83
- right: 0;
84
- z-index: 3;
85
- box-shadow: -2px 0 5px #0002;
86
- }
87
- }
88
- ```
@@ -1,7 +0,0 @@
1
- {
2
- "$schema": "https://unpkg.com/@7n/rules/schemas/concern.json",
3
- "lint": {
4
- "scope": "full",
5
- "glob": ["**/*.vue", "**/*.scss", "**/*.css"]
6
- }
7
- }
@@ -1,9 +0,0 @@
1
- ---
2
- type: Directory Index
3
- title: npm/rules/style/admin_table
4
- resource: npm/rules/style/admin_table/
5
- ---
6
-
7
- | Файл | Тип |
8
- | ------------------- | --------- |
9
- | [main.mjs](main.md) | JS Module |
@@ -1,14 +0,0 @@
1
- ---
2
- type: JS Module
3
- title: main.mjs
4
- resource: npm/rules/style/admin_table/main.mjs
5
- docgen:
6
- crc: 9e484318
7
- ---
8
-
9
- ## Огляд
10
-
11
- Детектор concern-а `admin_table` (read-only, whole-repo): якщо десь у `.vue`-файлі
12
- використано клас `n-admin-table`, він має бути визначений хоч в одному `.scss`/`.css`/`.vue`
13
- файлі проєкту, інакше — порушення `missing-admin-table-style`. Потребує whole-repo
14
- сканування (usage і definition можуть бути в різних файлах), тому не залежить від `ctx.files`.
@@ -1,46 +0,0 @@
1
- /** @see ./docs/main.md */
2
- import { readFile } from 'node:fs/promises'
3
-
4
- import { createViolationReporter } from '../../../scripts/lib/lint-surface/violation-reporter.mjs'
5
- import { walkDir } from '../../../scripts/utils/walkDir.mjs'
6
-
7
- const RELEVANT_RE = /\.(?:vue|scss|css)$/u
8
- const USAGE_RE = /\bn-admin-table\b/u
9
- const DEFINITION_RE = /\.n-admin-table\b/u
10
-
11
- /**
12
- * Detector style/admin_table (read-only, whole-repo): якщо десь у `.vue` використано
13
- * клас `n-admin-table`, він має бути визначений хоч в одному `.scss`/`.css`/`.vue`
14
- * (guide: `admin_table.mdc`). Для усунення false positives — крос-файлова перевірка,
15
- * тож потребує whole-repo сканування незалежно від `ctx.files`.
16
- * @param {import('../../../scripts/lib/lint-surface/types.mjs').LintContext} ctx контекст lint-прогону (cwd)
17
- * @returns {Promise<import('../../../scripts/lib/lint-surface/types.mjs').LintResult>} результат зі зібраними violations
18
- */
19
- export async function lint(ctx) {
20
- const reporter = createViolationReporter(ctx)
21
- const { fail } = reporter
22
- const cwd = ctx.cwd
23
-
24
- /** @type {string[]} */
25
- const files = []
26
- await walkDir(cwd, f => {
27
- if (RELEVANT_RE.test(f)) files.push(f)
28
- })
29
-
30
- let used = false
31
- let defined = false
32
- for (const file of files) {
33
- const content = await readFile(file, 'utf8')
34
- if (!used && file.endsWith('.vue') && USAGE_RE.test(content)) used = true
35
- if (!defined && DEFINITION_RE.test(content)) defined = true
36
- if (used && defined) break
37
- }
38
-
39
- if (used && !defined) {
40
- fail(
41
- 'Клас `.n-admin-table` використовується у `.vue`, але не визначений у жодному `.scss`/`.css` (guide: style/admin_table.mdc) — додай фікс до app.scss',
42
- 'missing-admin-table-style'
43
- )
44
- }
45
- return reporter.result()
46
- }
@@ -1,21 +0,0 @@
1
- ## Кольори: quasar-variables.scss і app.scss
2
-
3
- Основні кольори визначай виключно через стандартні Quasar-змінні: `$primary`, `$secondary`, `$accent`, `$positive`, `$negative`, `$warning`.
4
-
5
- Якщо потрібен додатковий колір — визнач його в `quasar-variables.scss`, і **обов'язково** додай до `app.scss` відповідні `.text-*` / `.bg-*` класи:
6
-
7
- ```scss
8
- /* quasar-variables.scss */
9
- $white-a1: color.adjust(white, $alpha: -0.85);
10
- ```
11
-
12
- ```scss
13
- /* app.scss */
14
- .text-white-a1 {
15
- color: $white-a1 !important;
16
- }
17
-
18
- .bg-white-a1 {
19
- background-color: $white-a1 !important;
20
- }
21
- ```
@@ -1,3 +0,0 @@
1
- {
2
- "$schema": "https://unpkg.com/@7n/rules/schemas/concern.json"
3
- }
@@ -1,7 +0,0 @@
1
- {
2
- "$schema": "https://unpkg.com/@7n/rules/schemas/concern.json",
3
- "lint": {
4
- "scope": "full",
5
- "glob": ["**/*.vue", "**/*.scss", "**/*.css"]
6
- }
7
- }
@@ -1,9 +0,0 @@
1
- ---
2
- type: Directory Index
3
- title: npm/rules/style/gap
4
- resource: npm/rules/style/gap/
5
- ---
6
-
7
- | Файл | Тип |
8
- | ------------------- | --------- |
9
- | [main.mjs](main.md) | JS Module |
@@ -1,15 +0,0 @@
1
- ---
2
- type: JS Module
3
- title: main.mjs
4
- resource: npm/rules/style/gap/main.mjs
5
- docgen:
6
- crc: dcba23e0
7
- ---
8
-
9
- ## Огляд
10
-
11
- Детектор concern-а `gap` (read-only, whole-repo): кожен суфікс утиліти
12
- `.n-gap-{xs,sm,md,lg}`, використаний у `.vue`-файлі, має бути визначений хоч в одному
13
- `.scss`/`.css`/`.vue` файлі проєкту — інакше порушення `missing-gap-style` для цього
14
- суфіксу. Суфікси відстежуються незалежно один від одного, тож часткове покриття все одно
15
- виявляє відсутній. Whole-repo сканування, не залежить від `ctx.files`.
@@ -1,22 +0,0 @@
1
- ## Gap між flex/grid-елементами — .n-gap-*
2
-
3
- Для відступів між плаваючими елементами (flex, grid) використовуй класи `.n-gap-*` замість `q-gutter-*`. Якщо класів немає в `app.scss` — додай:
4
-
5
- ```scss
6
- // GAP
7
- .n-gap-xs {
8
- gap: 4px;
9
- }
10
-
11
- .n-gap-sm {
12
- gap: 8px;
13
- }
14
-
15
- .n-gap-md {
16
- gap: 16px;
17
- }
18
-
19
- .n-gap-lg {
20
- gap: 24px;
21
- }
22
- ```
@@ -1,51 +0,0 @@
1
- /** @see ./docs/main.md */
2
- import { readFile } from 'node:fs/promises'
3
-
4
- import { createViolationReporter } from '../../../scripts/lib/lint-surface/violation-reporter.mjs'
5
- import { walkDir } from '../../../scripts/utils/walkDir.mjs'
6
-
7
- const RELEVANT_RE = /\.(?:vue|scss|css)$/u
8
- const USAGE_RE = /\bn-gap-(xs|sm|md|lg)\b/gu
9
- const DEFINITION_RE = /\.n-gap-(xs|sm|md|lg)\b/gu
10
-
11
- /**
12
- * Detector style/gap (read-only, whole-repo): кожен суфікс `.n-gap-{xs,sm,md,lg}`,
13
- * використаний у `.vue`, має бути визначений хоч в одному `.scss`/`.css`/`.vue`
14
- * (guide: `gap.mdc`). Крос-файлова перевірка usage↔definition — потребує whole-repo
15
- * сканування незалежно від `ctx.files`.
16
- * @param {import('../../../scripts/lib/lint-surface/types.mjs').LintContext} ctx контекст lint-прогону (cwd)
17
- * @returns {Promise<import('../../../scripts/lib/lint-surface/types.mjs').LintResult>} результат зі зібраними violations
18
- */
19
- export async function lint(ctx) {
20
- const reporter = createViolationReporter(ctx)
21
- const { fail } = reporter
22
- const cwd = ctx.cwd
23
-
24
- /** @type {string[]} */
25
- const files = []
26
- await walkDir(cwd, f => {
27
- if (RELEVANT_RE.test(f)) files.push(f)
28
- })
29
-
30
- /** @type {Set<string>} */
31
- const used = new Set()
32
- /** @type {Set<string>} */
33
- const defined = new Set()
34
- for (const file of files) {
35
- const content = await readFile(file, 'utf8')
36
- if (file.endsWith('.vue')) {
37
- for (const m of content.matchAll(USAGE_RE)) used.add(m[1])
38
- }
39
- for (const m of content.matchAll(DEFINITION_RE)) defined.add(m[1])
40
- }
41
-
42
- for (const suffix of used) {
43
- if (!defined.has(suffix)) {
44
- fail(
45
- `Клас \`.n-gap-${suffix}\` використовується у \`.vue\`, але не визначений у жодному \`.scss\`/\`.css\` (guide: style/gap.mdc) — додай клас до app.scss`,
46
- 'missing-gap-style'
47
- )
48
- }
49
- }
50
- return reporter.result()
51
- }
@@ -1,7 +0,0 @@
1
- {
2
- "$schema": "https://unpkg.com/@7n/rules/schemas/concern.json",
3
- "lint": {
4
- "scope": "per-file",
5
- "glob": ["**/*.{css,scss,vue}"]
6
- }
7
- }