@nitra/cursor 1.28.8 → 1.29.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.
- package/CHANGELOG.md +13 -0
- package/package.json +1 -1
- package/rules/ci4/ci4.mdc +7 -1
- package/rules/test/js/data/stryker_config/stryker-vue-macros-ignorer.mjs +47 -0
- package/rules/test/js/data/stryker_config/stryker.config.vue.baseline.mjs +23 -0
- package/rules/test/js/data/vitest_config/vitest.config.baseline.js +4 -0
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,19 @@
|
|
|
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.1] - 2026-05-28
|
|
8
|
+
|
|
9
|
+
### Fixed
|
|
10
|
+
|
|
11
|
+
- **`rules/test/js/data/vitest_config/vitest.config.baseline.js`** canon — додано `exclude: ['**/node_modules/**', '**/dist/**', '**/reports/stryker/**']`. Без exclude vitest пiдхоплює sandbox-копії тестів зі `reports/stryker/.tmp/sandbox-…/`, що залишилися від інкрементальних або аборнутих Stryker-прогонів; ці тести запускаються поза реальним repo root і фейляться (типово — `integration-repo-checks.test.mjs`, яке очікує bun.lock, bunfig.toml, кореневий `package.json`). Дзеркальна правка у `npm/vitest.config.js` для самого cursor-репо.
|
|
12
|
+
|
|
13
|
+
## [1.29.0] - 2026-05-28
|
|
14
|
+
|
|
15
|
+
### Changed
|
|
16
|
+
|
|
17
|
+
- **`rules/ci4/ci4.mdc`** (`version` 2.0 → 2.1) — додано секцію **«Зв'язок із `.cursor/rules`»**: архітектурна документація у `docs/` не дублює зміст `.cursor/rules/*.mdc` (операційні правила лінту, тестів, CHANGELOG, версіонування), а посилається на потрібне правило через його ім'я у бектиках (наприклад, `див. **`changelog`**`). Дублікати розходяться з оригіналом і ламають automatic-перевірки `npx @nitra/cursor fix`/`check`; правки робляться в одному місці — у самому `.mdc`.
|
|
18
|
+
|
|
19
|
+
|
|
7
20
|
## [1.28.8] - 2026-05-28
|
|
8
21
|
|
|
9
22
|
### Added
|
package/package.json
CHANGED
package/rules/ci4/ci4.mdc
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
description: Архітектурна документація продукту — Markdown як джерело істини; рекомендований стек arc42 + Diátaxis + ADR (MADR v4, формат описаний у правилі `adr`) + C4 як набір нотацій; гібридна модель manual + autogen-зон, що регенеруються з accepted ADR; MkDocs Material як viewer з collapsible engineer-блоками для змішаної аудиторії
|
|
3
3
|
alwaysApply: true
|
|
4
|
-
version: '2.
|
|
4
|
+
version: '2.1'
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
Архітектурна документація проєкту живе у Markdown поряд із кодом. Це не довідник «для людей із порталу архітектора» — це **джерело істини**, з якого LLM-агент і людина читають намір системи перед будь-якою зміною коду. Тому правила нижче — не оформлення, а робочий процес: який стек використовуємо, як зберігаємо рішення, як автоматично перегенеровуємо проекції з ADR і як рендеримо для змішаної аудиторії (менеджери + інженери + ops).
|
|
@@ -319,6 +319,12 @@ ADR (`docs/adr/<slug>.md`) — джерело правди для autogen-про
|
|
|
319
319
|
|
|
320
320
|
Архітектурні артефакти — частина **користувацької документації**, а не закритий артефакт для команди. Контекстна діаграма (C4 рівень 1) і контейнерна (рівень 2) живуть там, де читач шукає вступ у проєкт — у `explanation/architecture.md`, не у відокремленій теці «for-architects». MkDocs Material рендерить це з collapsible-блоками, тому менеджер бачить прозу, інженер провалюється в деталі.
|
|
321
321
|
|
|
322
|
+
## Зв'язок із `.cursor/rules`
|
|
323
|
+
|
|
324
|
+
`.cursor/rules/*.mdc` — джерело правди для **операційних правил** проєкту: як запускати лінт і тести, як оформлювати CHANGELOG, як версіонувати модулі, які прапорці передавати інструментам тощо. Архітектурна документація у `docs/` **не дублює** ці правила і не переказує їх своїми словами. Дублікат миттєво розходиться з оригіналом, ламає механіку automatic-перевірок (`npx @nitra/cursor fix`/`check`) і вимагає двох правок при кожній зміні — одна з них неминуче пропускається.
|
|
325
|
+
|
|
326
|
+
Замість дублювання — **відсилка** на конкретне правило через його ім'я у бектиках: «див. правило **`changelog`**», «див. **`n-lint`**», «деталі формату — у правилі **`adr`**». Відсилка веде читача (людину чи LLM-агента) до єдиного джерела істини; коли правило еволюціонує, документація лишається коректною без правки. Якщо `.cursor/rule` потребує доповнення або уточнення — оновлюй сам `.mdc`, а не копіюй його зміст у `docs/`.
|
|
327
|
+
|
|
322
328
|
## Інструменти
|
|
323
329
|
|
|
324
330
|
- **Claude Code** як runner — slash-команда `/regen-docs` або post-commit hook на зміни `docs/adr/**`
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Stryker `Ignore`-plugin: пропускає мутації виклику Vue `<script setup>`-макросів
|
|
3
|
+
* (`defineProps`, `defineEmits`, `defineModel`, `defineSlots`, `defineExpose`,
|
|
4
|
+
* `defineOptions`). Без цього Stryker обгортає аргументи макроса у тернарний
|
|
5
|
+
* coverage-вираз (`stryMutAct_9fa48(...) ? {} : (stryCov_9fa48(...), {...})`),
|
|
6
|
+
* а `@vue/compiler-sfc` падає з помилкою:
|
|
7
|
+
*
|
|
8
|
+
* defineProps() in <script setup> cannot reference locally declared variables
|
|
9
|
+
*
|
|
10
|
+
* бо макроси повинні бути статично-аналізованими на етапі compile-sfc.
|
|
11
|
+
*
|
|
12
|
+
* Стандартний Stryker plugin-loader (див. `@stryker-mutator/core/.../plugin-loader.js`)
|
|
13
|
+
* чекає експорт `strykerPlugins: Plugin[]`. У `stryker.config.mjs` файл цього
|
|
14
|
+
* плагіна додається у `plugins: ['./stryker-vue-macros-ignorer.mjs']`, а в
|
|
15
|
+
* `ignorers: ['vue-macros']` активується конкретно цей ignorer по імені.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
const VUE_SETUP_MACROS = new Set([
|
|
19
|
+
'defineProps',
|
|
20
|
+
'defineEmits',
|
|
21
|
+
'defineModel',
|
|
22
|
+
'defineSlots',
|
|
23
|
+
'defineExpose',
|
|
24
|
+
'defineOptions'
|
|
25
|
+
])
|
|
26
|
+
|
|
27
|
+
const IGNORE_MESSAGE = 'Vue <script setup> macro call cannot be mutated (defineProps/defineEmits/etc. must be statically analyzable for @vue/compiler-sfc).'
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* @param {{isCallExpression: () => boolean, node: {callee: {type: string, name?: string}}}} path babel NodePath, переданий Stryker-instrumenter
|
|
31
|
+
* @returns {string | undefined} non-empty message — пропустити мутацію піддерева; undefined — продовжити
|
|
32
|
+
*/
|
|
33
|
+
export function shouldIgnore(path) {
|
|
34
|
+
if (!path.isCallExpression()) return
|
|
35
|
+
const callee = path.node.callee
|
|
36
|
+
if (callee.type !== 'Identifier') return
|
|
37
|
+
if (!VUE_SETUP_MACROS.has(callee.name)) return
|
|
38
|
+
return IGNORE_MESSAGE
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export const strykerPlugins = [
|
|
42
|
+
{
|
|
43
|
+
kind: 'Ignore',
|
|
44
|
+
name: 'vue-macros',
|
|
45
|
+
value: { shouldIgnore }
|
|
46
|
+
}
|
|
47
|
+
]
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/** @type {import('@stryker-mutator/core').PartialStrykerOptions} */
|
|
2
|
+
export default {
|
|
3
|
+
testRunner: 'vitest',
|
|
4
|
+
vitest: { configFile: 'vitest.config.js' },
|
|
5
|
+
// perTest: Stryker запускає лише тести, що покривають мутовану лінію — головний приріст
|
|
6
|
+
// швидкості проти command runner (де треба було б ганяти ввесь test-suite на кожен мутант).
|
|
7
|
+
coverageAnalysis: 'perTest',
|
|
8
|
+
// concurrency: за замовч. Stryker обирає os.cpus().length - 1.
|
|
9
|
+
// inPlace більше не потрібен — vitest-runner ізолює мутантів у пам'яті через AST-patching,
|
|
10
|
+
// без копіювання node_modules у sandbox (стара проблема command runner у Bun monorepo).
|
|
11
|
+
tempDirName: 'reports/stryker/.tmp',
|
|
12
|
+
reporters: ['json', 'clear-text'],
|
|
13
|
+
jsonReporter: { fileName: 'reports/stryker/mutation.json' },
|
|
14
|
+
// incremental: зберігає результати між запусками, відновлює після краш/kill.
|
|
15
|
+
// Дає ~262× прискорення на noop-прогонах (див. benchmarks/runner-comparison/SPIKE.md).
|
|
16
|
+
incremental: true,
|
|
17
|
+
incrementalFile: 'reports/stryker/incremental.json',
|
|
18
|
+
// Local plugin: пропускає мутацію Vue <script setup>-макросів (defineProps/Emits/Model/
|
|
19
|
+
// Slots/Expose/Options). Інакше Stryker огортає аргументи у coverage-тернарник, який
|
|
20
|
+
// @vue/compiler-sfc не може статично проаналізувати і падає при компіляції SFC.
|
|
21
|
+
plugins: ['@stryker-mutator/vitest-runner', './stryker-vue-macros-ignorer.mjs'],
|
|
22
|
+
ignorers: ['vue-macros']
|
|
23
|
+
}
|
|
@@ -5,6 +5,10 @@ export default defineConfig({
|
|
|
5
5
|
// Підхоплюються обидві основні розкладки: тести поряд із кодом (rule `test`-конвенція —
|
|
6
6
|
// у піддиректоріях `tests/`) і top-level integration suites у `<root>/tests/`.
|
|
7
7
|
include: ['**/*.test.{js,mjs}', 'tests/**/*.test.{js,mjs}'],
|
|
8
|
+
// reports/stryker/.tmp/ містить sandbox-копії тестів від Stryker (incremental
|
|
9
|
+
// або aborted-runs); без exclude vitest run --coverage їх підхоплює і вони
|
|
10
|
+
// фейляться, бо запускаються поза реальним repo root.
|
|
11
|
+
exclude: ['**/node_modules/**', '**/dist/**', '**/reports/stryker/**'],
|
|
8
12
|
environment: 'node',
|
|
9
13
|
// `pool: 'forks'` — defense-in-depth ізоляція процесів між test-файлами.
|
|
10
14
|
// У default `pool: 'threads'` усі workers ділять один процес → паралельний
|