@nitra/cursor 1.29.2 → 1.29.3
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
CHANGED
|
@@ -4,6 +4,18 @@
|
|
|
4
4
|
|
|
5
5
|
Формат — [Keep a Changelog](https://keepachangelog.com/uk/1.1.0/), нумерація — [SemVer](https://semver.org/lang/uk/).
|
|
6
6
|
|
|
7
|
+
## [1.29.3] - 2026-05-29
|
|
8
|
+
|
|
9
|
+
### Changed
|
|
10
|
+
|
|
11
|
+
- **`rules/test/js/stryker_config.mjs`** — концерн `stryker_config` додає у кореневий `.gitignore` ще й `**/coverage/` (весь ефемерний output vitest v8 coverage: `lcov.info` + HTML `lcov-report/`) поряд із `**/reports/stryker/`. Coverage регенерується кожним прогоном, фінальні метрики живуть у `COVERAGE.md`; gitignore не заважає `n-cursor coverage` читати `lcov.info` у тому ж прогоні. Секцію .gitignore перейменовано на `# Test artifacts: Stryker + coverage`. Документація — `test.mdc`.
|
|
12
|
+
- **`rules/test/js/stryker_config.mjs`**, **`rules/test/js/cargo_mutants_config.mjs`**, **`rules/tauri/js/cargo_mutants_config.mjs`** — `check()` → `check(cwd = process.cwd())` за test.mdc canon (production functions приймають перший параметр `cwd`). До цього усі три концерни читали лише `process.cwd()`, через що тести змушені були викликати `process.chdir(dir)` (з обходом regex-сканера `no-process-chdir` через `import { chdir } from 'node:process'`). Stryker крутить vitest у threads-pool (`@stryker-mutator/vitest-runner` форсує `pool: 'threads'`, перетираючи `pool: 'forks'` у `vitest.config.js`), де `process.chdir` не підтримується → dry-run обривався з `process.chdir() is not supported in workers`. Тести у `tests/stryker_config.test.mjs`, `tests/cargo_mutants_config.test.mjs` (обидва правила) переписано на `runCheckIn(dir) → check(dir)` без chdir.
|
|
13
|
+
|
|
14
|
+
### Fixed
|
|
15
|
+
|
|
16
|
+
- **`tests/integration-repo-checks.test.mjs`** — `test.skipIf(env.STRYKER_MUTATOR_WORKER)` для test `узгоджені з поточним деревом cursor` (env-import із `node:process` за `js-run.mdc`). Stryker копіює репо у `reports/stryker/.tmp/sandbox-XXX/` і запускає тести звідти; `REPO_ROOT = join(import.meta.dirname, '..', '..')` резолвиться у sandbox-копію, де `checkNpmModule` валідує CHANGELOG vs HEAD-version без живого `.git/` і повертає 1 → Stryker dry-run обривається (`ConfigError: There were failed tests in the initial test run.`). Для mutation-analysis інтеграція проти живого дерева не дає додаткової сигналу понад per-rule unit-тести.
|
|
17
|
+
- **`rules/js-lint/coverage/coverage.mjs:236`** `runStryker` — `bunx` → `npx` для запуску `@stryker-mutator/core`. Bunx **завжди** інсталює пакет у `T/bunx-<uid>-<pkg>@latest/node_modules/` і запускає Stryker звідти, навіть коли локальний install уже існує у hoisted node_modules. Stryker plugin-discovery (`@stryker-mutator/*`) globится відносно core-install-каталогу (`core/dist/src/di/plugin-loader.js:79` → `../../../../../@stryker-mutator/*`) — у bunx-temp бачить лише `core/api/instrumenter/util` (всі чотири у `IGNORED_PACKAGES`), а локально встановлений `@stryker-mutator/vitest-runner` залишається невидимим. Worker-процеси падають з `Cannot find TestRunner plugin "vitest". In fact, no TestRunner plugins were loaded.`. До зняття `mutate`-обмеження (1.29.2) баг маскувався: при єдиному файлі у scope Stryker incremental-кеш мав усі 141 мутант → fresh-workers не стартували → плагін не потрібен. Після розширення `mutate` 25052 мутантів вимагали свіжих workers — баг проявився. `npx` шукає у локальному `node_modules/.bin/` (walking up), запускає Stryker з cursor-репо install, де поряд лежить vitest-runner.
|
|
18
|
+
|
|
7
19
|
## [1.29.2] - 2026-05-29
|
|
8
20
|
|
|
9
21
|
### Changed
|
package/package.json
CHANGED
|
@@ -233,7 +233,14 @@ const defaultRunner = {
|
|
|
233
233
|
return r.status ?? 1
|
|
234
234
|
},
|
|
235
235
|
runStryker({ cwd }) {
|
|
236
|
-
|
|
236
|
+
// `npx`, не `bunx`: bunx завжди ставить пакет у `T/bunx-<uid>-<pkg>@latest` і запускає
|
|
237
|
+
// Stryker звідти. Плагін-discovery у Stryker (`@stryker-mutator/*`) globится відносно
|
|
238
|
+
// CORE-install-каталогу (`core/dist/src/di/plugin-loader.js` → `../../../../../@stryker-mutator/*`),
|
|
239
|
+
// тож у bunx-temp бачить лише `core/api/instrumenter/util` (усі в IGNORED_PACKAGES) — а локально
|
|
240
|
+
// встановлений `@stryker-mutator/vitest-runner` залишається невидимим, і workers падають з
|
|
241
|
+
// `Cannot find TestRunner plugin "vitest"`. `npx` ходить угору по `node_modules/.bin/` і
|
|
242
|
+
// запускає Stryker з локального hoisted-install, де поряд лежить vitest-runner.
|
|
243
|
+
const r = spawnSync('npx', ['@stryker-mutator/core', 'run'], { cwd, stdio: 'inherit', env: process.env })
|
|
237
244
|
return r.status ?? 1
|
|
238
245
|
}
|
|
239
246
|
}
|
|
@@ -135,11 +135,11 @@ async function processOneSrcTauri(srcTauriDir, cwd, reporter) {
|
|
|
135
135
|
}
|
|
136
136
|
|
|
137
137
|
/**
|
|
138
|
+
* @param {string} [cwd] корінь проєкту (default: `process.cwd()` — CLI-сумісність)
|
|
138
139
|
* @returns {Promise<number>} 0 — OK або silently skipped, 1 — порушення
|
|
139
140
|
*/
|
|
140
|
-
export async function check() {
|
|
141
|
+
export async function check(cwd = process.cwd()) {
|
|
141
142
|
const reporter = createCheckReporter()
|
|
142
|
-
const cwd = process.cwd()
|
|
143
143
|
const srcTauriDirs = await findSrcTauriDirs(cwd)
|
|
144
144
|
if (srcTauriDirs.length === 0) {
|
|
145
145
|
return reporter.getExitCode()
|
|
@@ -23,11 +23,11 @@ const HERE = dirname(fileURLToPath(import.meta.url))
|
|
|
23
23
|
const BASELINE_PATH = join(HERE, 'data', 'cargo_mutants_config', 'mutants.toml.baseline')
|
|
24
24
|
|
|
25
25
|
/**
|
|
26
|
+
* @param {string} [cwd] корінь проєкту (default: `process.cwd()` — CLI-сумісність)
|
|
26
27
|
* @returns {Promise<number>} 0 — OK або silently skipped, 1 — порушення
|
|
27
28
|
*/
|
|
28
|
-
export async function check() {
|
|
29
|
+
export async function check(cwd = process.cwd()) {
|
|
29
30
|
const reporter = createCheckReporter()
|
|
30
|
-
const cwd = process.cwd()
|
|
31
31
|
const config = await readNCursorConfigLite(cwd)
|
|
32
32
|
|
|
33
33
|
// Self-gate: rust має бути enabled
|
|
@@ -33,11 +33,14 @@ const STRYKER_VUE_PLUGIN_PATH = join(HERE, 'data', 'stryker_config', 'stryker-vu
|
|
|
33
33
|
const STRYKER_VUE_PLUGIN_FILENAME = 'stryker-vue-macros-ignorer.mjs'
|
|
34
34
|
const VITEST_BASELINE_PATH = join(HERE, 'data', 'vitest_config', 'vitest.config.baseline.js')
|
|
35
35
|
|
|
36
|
-
//
|
|
37
|
-
//
|
|
38
|
-
// якщо користувач додасть інші reporter-и).
|
|
39
|
-
//
|
|
40
|
-
|
|
36
|
+
// Тест-артефакти для .gitignore (подвійний-зірочка-префікс — для monorepo workspaces):
|
|
37
|
+
// - `**/reports/stryker/` — увесь каталог Stryker-output-у (`tempDirName` backup'и,
|
|
38
|
+
// mutation.json, HTML/dashboard-репорти якщо користувач додасть інші reporter-и).
|
|
39
|
+
// - `**/coverage/` — весь output vitest v8 coverage (`lcov.info` + HTML `lcov-report/`).
|
|
40
|
+
// Ефемерний: регенерується кожним прогоном; фінальні метрики живуть у `COVERAGE.md`.
|
|
41
|
+
// Gitignore не заважає `n-cursor coverage` читати `lcov.info` у тому ж прогоні.
|
|
42
|
+
// Покриваємо каталогами замість перелічування під-патернів.
|
|
43
|
+
const TEST_GITIGNORE_ENTRIES = ['**/reports/stryker/', '**/coverage/']
|
|
41
44
|
|
|
42
45
|
// .vue detection: scope — `<jsRoot>/src/**/*.vue` (як і Stryker mutate defaults для src/);
|
|
43
46
|
// skip build-артефактів і чужих node_modules, щоб не вмикати vue-варіант через transitive deps.
|
|
@@ -75,11 +78,11 @@ async function ensureBaselineFile(reporter, cwd, baselinePath, target, label) {
|
|
|
75
78
|
}
|
|
76
79
|
|
|
77
80
|
/**
|
|
81
|
+
* @param {string} [cwd] корінь проєкту (default: `process.cwd()` — CLI-сумісність)
|
|
78
82
|
* @returns {Promise<number>} 0 — OK або silently skipped, 1 — порушення
|
|
79
83
|
*/
|
|
80
|
-
export async function check() {
|
|
84
|
+
export async function check(cwd = process.cwd()) {
|
|
81
85
|
const reporter = createCheckReporter()
|
|
82
|
-
const cwd = process.cwd()
|
|
83
86
|
const config = await readNCursorConfigLite(cwd)
|
|
84
87
|
|
|
85
88
|
// Self-gate: js-lint має бути enabled
|
|
@@ -127,11 +130,12 @@ export async function check() {
|
|
|
127
130
|
await ensureBaselineFile(reporter, cwd, VITEST_BASELINE_PATH, join(jsRoot, 'vitest.config.js'), 'vitest.config.js')
|
|
128
131
|
}
|
|
129
132
|
|
|
130
|
-
// Гарантуємо що Stryker
|
|
131
|
-
// покривають усі workspaces через `**/`-префікс
|
|
132
|
-
|
|
133
|
+
// Гарантуємо що тест-артефакти (Stryker output, lcov HTML-звіт) ніколи не
|
|
134
|
+
// потрапляють у commit. Patterns покривають усі workspaces через `**/`-префікс
|
|
135
|
+
// (єдиний root .gitignore).
|
|
136
|
+
const { added } = await ensureGitignoreEntries(cwd, TEST_GITIGNORE_ENTRIES, 'Test artifacts: Stryker + coverage (test.mdc)')
|
|
133
137
|
if (added.length > 0) {
|
|
134
|
-
reporter.pass(`.gitignore: додано
|
|
138
|
+
reporter.pass(`.gitignore: додано тест-патерни (${added.join(', ')}) (test.mdc)`)
|
|
135
139
|
}
|
|
136
140
|
return reporter.getExitCode()
|
|
137
141
|
}
|
package/rules/test/test.mdc
CHANGED
|
@@ -153,4 +153,9 @@ Customization (mutate patterns, exclude rules, timeout) — відповідал
|
|
|
153
153
|
|
|
154
154
|
Якщо інше правило спеціалізує mutation-behavior — воно зобов'язане **доповнювати** існуючий `.cargo/mutants.toml` без дублювання (додавати лише відсутні ключі) і **не перетирати** ручні налаштування. Послідовний запуск `npx @nitra/cursor fix test` після `fix tauri` не має скидати tauri-tuning, і навпаки — повторний `fix tauri` не дублює секції.
|
|
155
155
|
|
|
156
|
-
Додатково: коли `js-lint` enabled, концерн `stryker_config` без дублювання додає у кореневий `.gitignore`
|
|
156
|
+
Додатково: коли `js-lint` enabled, концерн `stryker_config` без дублювання додає у кореневий `.gitignore` тест-патерни:
|
|
157
|
+
|
|
158
|
+
- `**/reports/stryker/` — увесь каталог Stryker-output-у (backup'и `tempDirName`, `mutation.json`, HTML/dashboard-репорти якщо додасте інші reporter-и).
|
|
159
|
+
- `**/coverage/` — весь output vitest v8 coverage (`lcov.info` + HTML `lcov-report/`). Ефемерний: регенерується кожним прогоном, фінальні метрики живуть у `COVERAGE.md`. Gitignore не заважає `n-cursor coverage` читати `lcov.info` у тому ж прогоні.
|
|
160
|
+
|
|
161
|
+
Це запобігає випадковому коміту build-артефактів.
|