@nitra/cursor 1.8.198 → 1.8.199
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +11 -0
- package/bin/n-cursor.js +33 -1
- package/package.json +1 -1
- package/scripts/auto-rules.mjs +41 -2
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,17 @@
|
|
|
4
4
|
|
|
5
5
|
Формат — [Keep a Changelog](https://keepachangelog.com/uk/1.1.0/), нумерація — [SemVer](https://semver.org/lang/uk/).
|
|
6
6
|
|
|
7
|
+
## [1.8.199] - 2026-05-07
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
- `auto-rules.mjs`: автоматична міграція застарілих rule-id у `.n-cursor.json` через карту `RULE_MIGRATIONS`. Перший зареєстрований запис — `image` → `image-compress` + `image-avif` (split з 1.8.197). Застосовується і до `rules`, і до `disable-rules`, з дедуплікацією. CLI `n-cursor.js` логує `📦 Авто-міграція .n-cursor.json: image → image-compress, image-avif` перед нормалізацією, потім записує оновлений конфіг (як і раніше — лише якщо вміст реально змінився).
|
|
12
|
+
- `tests/auto-rules.test.mjs`: тести `migrateRuleIds` (порядок, дедуплікація, no-op для актуальних id), `detectLegacyRuleIds`, `mergeConfigWithAutoDetected` з legacy `image` у `rules`/`disable-rules`/конфлікті з `image-compress`.
|
|
13
|
+
|
|
14
|
+
### Changed
|
|
15
|
+
|
|
16
|
+
- `n-cursor.js`: розширено імпорт з `auto-rules.mjs` (`detectLegacyRuleIds`, `RULE_MIGRATIONS`); виокремлено хелпер `logRuleMigrationsIfAny` (читає сирий конфіг, виводить пояснення, не мутує — мутацію виконує `migrateRuleIds` усередині `mergeConfigWithAutoDetected`). Завдяки цьому `npx @nitra/cursor` сам перебиває `image` на пару наступників — користувачу не треба руками правити `.n-cursor.json`.
|
|
17
|
+
|
|
7
18
|
## [1.8.198] - 2026-05-07
|
|
8
19
|
|
|
9
20
|
### Changed
|
package/bin/n-cursor.js
CHANGED
|
@@ -56,7 +56,13 @@ import { cwd } from 'node:process'
|
|
|
56
56
|
import { fileURLToPath } from 'node:url'
|
|
57
57
|
|
|
58
58
|
import { buildAgentsCommandBulletItems } from '../scripts/build-agents-commands.mjs'
|
|
59
|
-
import {
|
|
59
|
+
import {
|
|
60
|
+
detectAutoRulesAndSkills,
|
|
61
|
+
detectLegacyRuleIds,
|
|
62
|
+
mergeConfigWithAutoDetected,
|
|
63
|
+
normalizeIdList,
|
|
64
|
+
RULE_MIGRATIONS
|
|
65
|
+
} from '../scripts/auto-rules.mjs'
|
|
60
66
|
import { runStopHookCli } from '../scripts/claude-stop-hook.mjs'
|
|
61
67
|
import { ensureNitraCursorInRootDevDependencies } from '../scripts/ensure-nitra-cursor-dev-dependencies.mjs'
|
|
62
68
|
import { runLintGaCli } from '../scripts/lint-ga.mjs'
|
|
@@ -301,6 +307,7 @@ async function readConfig(paths = {}) {
|
|
|
301
307
|
} catch {
|
|
302
308
|
throw new Error(`Невірний JSON у файлі ${CONFIG_FILE}`)
|
|
303
309
|
}
|
|
310
|
+
logRuleMigrationsIfAny(config)
|
|
304
311
|
const normalized = await normalizeConfigWithAutoRules(config)
|
|
305
312
|
if (JSON.stringify(normalized) !== JSON.stringify(config)) {
|
|
306
313
|
await writeFile(configPath, `${JSON.stringify(normalized, null, 2)}\n`, 'utf8')
|
|
@@ -309,6 +316,31 @@ async function readConfig(paths = {}) {
|
|
|
309
316
|
return normalized
|
|
310
317
|
}
|
|
311
318
|
|
|
319
|
+
/**
|
|
320
|
+
* Якщо у `rules` чи `disable-rules` є застарілі rule-id з `RULE_MIGRATIONS`,
|
|
321
|
+
* виводить пояснювальний лог про автоматичну заміну (саму заміну виконує
|
|
322
|
+
* `migrateRuleIds` у `mergeConfigWithAutoDetected` — тут лише користувацька комунікація).
|
|
323
|
+
* @param {Record<string, unknown>} parsedConfig сирий обʼєкт `.n-cursor.json` після `JSON.parse`
|
|
324
|
+
* @returns {void}
|
|
325
|
+
*/
|
|
326
|
+
function logRuleMigrationsIfAny(parsedConfig) {
|
|
327
|
+
/** @type {Set<string>} */
|
|
328
|
+
const seen = new Set()
|
|
329
|
+
for (const key of /** @type {const} */ (['rules', 'disable-rules'])) {
|
|
330
|
+
const list = parsedConfig[key]
|
|
331
|
+
if (!Array.isArray(list)) continue
|
|
332
|
+
const legacy = detectLegacyRuleIds(normalizeIdList(list))
|
|
333
|
+
for (const id of legacy) seen.add(id)
|
|
334
|
+
}
|
|
335
|
+
if (seen.size === 0) return
|
|
336
|
+
console.log(`📦 Авто-міграція ${CONFIG_FILE}:`)
|
|
337
|
+
for (const id of seen) {
|
|
338
|
+
const replacement = RULE_MIGRATIONS[id].join(', ')
|
|
339
|
+
console.log(` • ${id} → ${replacement}`)
|
|
340
|
+
}
|
|
341
|
+
console.log('')
|
|
342
|
+
}
|
|
343
|
+
|
|
312
344
|
/**
|
|
313
345
|
* Витягує чисте ім'я файлу правила (без шляху, але зберігає .mdc)
|
|
314
346
|
* "npm/mdc/text.mdc" → "text.mdc"
|
package/package.json
CHANGED
package/scripts/auto-rules.mjs
CHANGED
|
@@ -49,6 +49,45 @@ export const AUTO_RULE_ORDER = Object.freeze([
|
|
|
49
49
|
/** Порядок автододавання skills відповідно до `auto-rules.md`. */
|
|
50
50
|
export const AUTO_SKILL_ORDER = Object.freeze(['abie-kustomize', 'fix', 'lint'])
|
|
51
51
|
|
|
52
|
+
/**
|
|
53
|
+
* Карта міграції застарілих rule-id у `.n-cursor.json` на актуальні.
|
|
54
|
+
* Застосовується автоматично при читанні конфігу (як для `rules`, так і для `disable-rules`).
|
|
55
|
+
* Приклад: `image` → `image-compress` + `image-avif` (правило розщеплене у 1.8.197).
|
|
56
|
+
*/
|
|
57
|
+
export const RULE_MIGRATIONS = Object.freeze(
|
|
58
|
+
/** @type {Record<string, readonly string[]>} */ ({
|
|
59
|
+
image: Object.freeze(['image-compress', 'image-avif'])
|
|
60
|
+
})
|
|
61
|
+
)
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Розгортає застарілі rule-id у списку згідно з `RULE_MIGRATIONS`. Зберігає порядок,
|
|
65
|
+
* дедуплікує. Чистий хелпер: не мутує вхід, не логує.
|
|
66
|
+
* @param {string[]} ids нормалізований список id (як з `normalizeIdList`)
|
|
67
|
+
* @returns {string[]} список з legacy-id, заміненими на нові; решта без змін
|
|
68
|
+
*/
|
|
69
|
+
export function migrateRuleIds(ids) {
|
|
70
|
+
/** @type {string[]} */
|
|
71
|
+
const out = []
|
|
72
|
+
for (const id of ids) {
|
|
73
|
+
const replacement = Object.hasOwn(RULE_MIGRATIONS, id) ? RULE_MIGRATIONS[id] : [id]
|
|
74
|
+
for (const newId of replacement) {
|
|
75
|
+
if (!out.includes(newId)) out.push(newId)
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
return out
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Повертає лише ті legacy rule-id зі списку, для яких є запис у `RULE_MIGRATIONS`.
|
|
83
|
+
* Використовується для людинозрозумілого логування міграції при синхронізації CLI.
|
|
84
|
+
* @param {string[]} ids нормалізований список id
|
|
85
|
+
* @returns {string[]} legacy id, які потребуватимуть заміни у `migrateRuleIds`
|
|
86
|
+
*/
|
|
87
|
+
export function detectLegacyRuleIds(ids) {
|
|
88
|
+
return ids.filter(id => Object.hasOwn(RULE_MIGRATIONS, id))
|
|
89
|
+
}
|
|
90
|
+
|
|
52
91
|
/**
|
|
53
92
|
* Граф залежностей між правилами (`auto-rules.md` синтаксис `rule - [other]`).
|
|
54
93
|
* Ключ варто автододати, коли всі правила-залежності вже додані до конфігу — щоб
|
|
@@ -649,9 +688,9 @@ export async function detectAutoRulesAndSkills({
|
|
|
649
688
|
* @returns {{ rules: string[], skills: string[] } & Record<string, unknown>} новий нормалізований конфіг
|
|
650
689
|
*/
|
|
651
690
|
export function mergeConfigWithAutoDetected({ config, detectedRules, detectedSkills }) {
|
|
652
|
-
const existingRules = normalizeIdList(config.rules)
|
|
691
|
+
const existingRules = migrateRuleIds(normalizeIdList(config.rules))
|
|
653
692
|
const existingSkills = normalizeIdList(config.skills)
|
|
654
|
-
const disableRules = normalizeIdList(config['disable-rules'])
|
|
693
|
+
const disableRules = migrateRuleIds(normalizeIdList(config['disable-rules']))
|
|
655
694
|
const disableSkills = normalizeIdList(config['disable-skills'])
|
|
656
695
|
|
|
657
696
|
const rules = [...existingRules]
|