@nitra/cursor 12.11.0 → 12.11.2

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 (71) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/bin/n-cursor.js +9 -27
  3. package/package.json +1 -1
  4. package/rules/adr/js/docs/hooks.md +0 -2
  5. package/rules/bun/js/docs/fix-layout.md +25 -0
  6. package/rules/bun/js/fix-layout.mjs +55 -0
  7. package/rules/changelog/js/docs/consistency.md +11 -13
  8. package/rules/changelog/js/docs/fix-consistency.md +27 -0
  9. package/rules/changelog/js/docs/index.md +2 -2
  10. package/rules/changelog/js/fix-consistency.mjs +50 -0
  11. package/rules/ci4/policy/vscode_extensions/docs/fix-vscode_extensions.md +21 -0
  12. package/rules/ci4/policy/vscode_extensions/fix-vscode_extensions.mjs +1 -0
  13. package/rules/ga/policy/vscode_extensions/docs/fix-vscode_extensions.md +22 -0
  14. package/rules/ga/policy/vscode_extensions/fix-vscode_extensions.mjs +1 -0
  15. package/rules/ga/policy/workflow_common/workflow_common.rego +15 -0
  16. package/rules/graphql/policy/vscode_extensions/docs/fix-vscode_extensions.md +21 -0
  17. package/rules/graphql/policy/vscode_extensions/fix-vscode_extensions.mjs +1 -0
  18. package/rules/js/js/docs/dep-policy.md +12 -10
  19. package/rules/js/policy/vscode_extensions/docs/fix-vscode_extensions.md +22 -0
  20. package/rules/js/policy/vscode_extensions/fix-vscode_extensions.mjs +1 -0
  21. package/rules/js-run/js/docs/fix-runtime.md +25 -0
  22. package/rules/js-run/js/fix-runtime.mjs +41 -0
  23. package/rules/k8s/policy/lint_k8s_yml/lint_k8s_yml.rego +57 -0
  24. package/rules/k8s/policy/lint_k8s_yml/target.json +4 -0
  25. package/rules/k8s/policy/lint_k8s_yml/template/lint-k8s.yml.snippet.yml +43 -0
  26. package/rules/nginx-default-tpl/policy/vscode_extensions/docs/fix-vscode_extensions.md +21 -0
  27. package/rules/nginx-default-tpl/policy/vscode_extensions/fix-vscode_extensions.mjs +1 -0
  28. package/rules/rego/policy/vscode_extensions/docs/fix-vscode_extensions.md +22 -0
  29. package/rules/rego/policy/vscode_extensions/fix-vscode_extensions.mjs +1 -0
  30. package/rules/rust/policy/vscode_extensions/docs/fix-vscode_extensions.md +22 -0
  31. package/rules/rust/policy/vscode_extensions/fix-vscode_extensions.mjs +1 -0
  32. package/rules/style/js/docs/fix-tooling.md +29 -0
  33. package/rules/style/js/fix-tooling.mjs +46 -0
  34. package/rules/style/policy/vscode_extensions/docs/fix-vscode_extensions.md +21 -0
  35. package/rules/style/policy/vscode_extensions/fix-vscode_extensions.mjs +1 -0
  36. package/rules/tauri/policy/vscode_extensions/docs/fix-vscode_extensions.md +21 -0
  37. package/rules/tauri/policy/vscode_extensions/fix-vscode_extensions.mjs +1 -0
  38. package/rules/text/policy/vscode_extensions/docs/fix-vscode_extensions.md +21 -0
  39. package/rules/text/policy/vscode_extensions/fix-vscode_extensions.mjs +1 -0
  40. package/rules/vue/js/docs/packages.md +0 -2
  41. package/scripts/docs/index.md +0 -2
  42. package/scripts/lib/discover-checkable-rules.mjs +1 -0
  43. package/scripts/lib/docs/discover-checkable-rules.md +13 -155
  44. package/scripts/lib/fix/discover-t0-patterns.mjs +83 -0
  45. package/scripts/lib/fix/docs/discover-t0-patterns.md +37 -0
  46. package/scripts/lib/fix/docs/llm-fix-apply.md +12 -10
  47. package/scripts/lib/fix/docs/llm-worker.md +6 -14
  48. package/scripts/lib/fix/docs/orchestrator.md +0 -2
  49. package/scripts/lib/fix/docs/t0.md +11 -10
  50. package/scripts/lib/fix/docs/vscode-ext-add.md +29 -0
  51. package/scripts/lib/fix/llm-fix-apply.mjs +34 -3
  52. package/scripts/lib/fix/llm-worker.mjs +24 -15
  53. package/scripts/lib/fix/t0.mjs +8 -119
  54. package/scripts/lib/fix/vscode-ext-add.mjs +45 -0
  55. package/rules/test/coverage/coverage.mjs +0 -317
  56. package/scripts/coverage-classify/apply.mjs +0 -67
  57. package/scripts/coverage-classify/cache.mjs +0 -77
  58. package/scripts/coverage-classify/docs/apply.md +0 -206
  59. package/scripts/coverage-classify/docs/cache.md +0 -207
  60. package/scripts/coverage-classify/docs/index.md +0 -14
  61. package/scripts/coverage-classify/docs/prompt.md +0 -136
  62. package/scripts/coverage-classify/docs/verdict-schema.md +0 -28
  63. package/scripts/coverage-classify/index.mjs +0 -114
  64. package/scripts/coverage-classify/prompt.mjs +0 -126
  65. package/scripts/coverage-classify/verdict-schema.mjs +0 -35
  66. package/scripts/coverage-fix-extract.mjs +0 -122
  67. package/scripts/coverage-fix.mjs +0 -119
  68. package/scripts/docs/coverage-fix-extract.md +0 -36
  69. package/scripts/docs/coverage-fix.md +0 -181
  70. package/skills/coverage-fix/SKILL.md +0 -131
  71. package/skills/coverage-fix/main.json +0 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # Changelog
2
2
 
3
+ ## [12.11.2] - 2026-06-25
4
+
5
+ ### Changed
6
+
7
+ - docs: файлова документація для fix-<concern>.mjs та суміжних файлів; feat(fix): розкладаємо T0-паттерни по правилах — fix-<concern>.mjs конвенція
8
+
9
+ ## [12.11.1] - 2026-06-25
10
+
11
+ ### Changed
12
+
13
+ - ♻️ refactor(scripts): T0-autofix контракт fix-<concern>.mjs — нова конвенція в scripts.mdc
14
+
3
15
  ## [12.11.0] - 2026-06-25
4
16
 
5
17
  ### Changed
package/bin/n-cursor.js CHANGED
@@ -64,7 +64,7 @@
64
64
  import { spawnSync } from 'node:child_process'
65
65
  import { existsSync } from 'node:fs'
66
66
  import { mkdir, readdir, readFile, rename, rm, unlink, writeFile } from 'node:fs/promises'
67
- import { basename, dirname, join } from 'node:path'
67
+ import { basename, dirname, join, resolve } from 'node:path'
68
68
  import { cwd, env } from 'node:process'
69
69
  import { fileURLToPath } from 'node:url'
70
70
 
@@ -1457,7 +1457,7 @@ async function runSync() {
1457
1457
  * `--root`-команди `doc-aggregate`/`rename-yaml-extensions`,
1458
1458
  * sub-лінтери) гард не зачіпає.
1459
1459
  */
1460
- const ROOT_GUARDED_COMMANDS = new Set([undefined, '', 'lint', 'coverage', 'change', 'release'])
1460
+ const ROOT_GUARDED_COMMANDS = new Set([undefined, '', 'lint', 'change', 'release'])
1461
1461
 
1462
1462
  /**
1463
1463
  * Короткий опис дії для тексту root-guard помилки за іменем команди.
@@ -1473,9 +1473,6 @@ function describeRootGuardedAction(cmd) {
1473
1473
  case 'lint': {
1474
1474
  return '`lint` за замовчуванням авто-fix лінтерів (oxfmt/eslint --fix/stylelint --fix) і конформності (--full) у поточному каталозі'
1475
1475
  }
1476
- case 'coverage': {
1477
- return '`coverage` генерує COVERAGE.md і Stryker-артефакти в поточному каталозі'
1478
- }
1479
1476
  case 'change': {
1480
1477
  return '`change` пише change-файл у .changes/ поточного каталогу'
1481
1478
  }
@@ -1493,7 +1490,7 @@ const [command, ...args] = process.argv.slice(2)
1493
1490
 
1494
1491
  try {
1495
1492
  // Root-guard до перших мутацій: дефолтний sync скаффолдить .cursor/.claude/CLAUDE.md/
1496
- // .n-cursor.json + bun install, а fix/lint/coverage/change/release переписують файли в CWD —
1493
+ // .n-cursor.json + bun install, а lint/change/release переписують файли в CWD —
1497
1494
  // усе це ключиться на cwd(). Запуск із піддиректорії git-репо (типово прямий
1498
1495
  // `bun npm/bin/n-cursor.js` не з кореня) зачепив би не той каталог → STOP. Read-only та
1499
1496
  // `--root`-команди (trace, graph, doc-aggregate, rename-yaml-extensions) не зачіпаємо.
@@ -1523,33 +1520,18 @@ try {
1523
1520
  // Дві ортогональні осі: --full (scope: весь репо vs дельта vs origin) × --read-only (behavior).
1524
1521
  // Позиційні (не-флаг) аргументи — фільтр правил конформності (напр. `lint changelog`):
1525
1522
  // прогнати лише конформність цих правил, без лінтер-скану (мапить колишній `fix <rule>`).
1526
- const rules = args.filter(a => !a.startsWith('-'))
1523
+ const cwdIdx = args.indexOf('--cwd')
1524
+ const cwdArg = cwdIdx !== -1 ? resolve(args[cwdIdx + 1]) : undefined
1525
+ const rules = args.filter((a, i) => !a.startsWith('-') && i !== cwdIdx + 1)
1527
1526
  process.exitCode = await runLint({
1528
1527
  full: args.includes('--full'),
1529
1528
  readOnly: args.includes('--read-only'),
1530
- rules
1529
+ rules,
1530
+ cwd: cwdArg
1531
1531
  })
1532
1532
 
1533
1533
  break
1534
1534
  }
1535
- case 'coverage': {
1536
- // n-cursor coverage — оркестратор покриття + мутаційного тестування з discovery
1537
- // провайдерів через .n-cursor.json#rules (test.mdc). --changed звужує scope до
1538
- // змінених від base файлів (flow-турнікет: лише vitest/Stryker по diff).
1539
- const { runCoverageCli } = await import('../rules/test/coverage/coverage.mjs')
1540
- process.exitCode = await runCoverageCli({ fix: args.includes('--fix'), changed: args.includes('--changed') })
1541
-
1542
- break
1543
- }
1544
- case 'coverage-fix': {
1545
- // n-cursor coverage-fix index|slice — read-only витяг вцілілих мутантів із
1546
- // COVERAGE.md для скілу n-coverage-fix. Важкий парсинг несе скрипт (0 LLM-
1547
- // токенів); агент отримує лише компактний index або зріз під один файл.
1548
- const { runCoverageFixCli } = await import('../scripts/coverage-fix-extract.mjs')
1549
- process.exitCode = await runCoverageFixCli(args)
1550
-
1551
- break
1552
- }
1553
1535
  case 'analyze-escalation': {
1554
1536
  // n-cursor analyze-escalation — читає весь escalation-лог (.n-cursor/fix-escalation.jsonl),
1555
1537
  // чанкує й просить хмарну avg-модель запропонувати, як зменшити LLM-залежність fix-
@@ -1634,7 +1616,7 @@ try {
1634
1616
  default: {
1635
1617
  console.error(`❌ Невідома команда: ${command}`)
1636
1618
  console.error(
1637
- ` Очікується: (без аргументів) синхронізація правил, rename-yaml-extensions, hook, adr-normalize-local, lint (включно зі scope: lint ga|rego|k8s|docker|text), coverage, coverage-fix, analyze-escalation, taze, start-check, release, skill, trace, doc-aggregate`
1619
+ ` Очікується: (без аргументів) синхронізація правил, rename-yaml-extensions, hook, adr-normalize-local, lint (включно зі scope: lint ga|rego|k8s|docker|text), analyze-escalation, taze, start-check, release, skill, trace, doc-aggregate`
1638
1620
  )
1639
1621
  process.exitCode = 1
1640
1622
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nitra/cursor",
3
- "version": "12.11.0",
3
+ "version": "12.11.2",
4
4
  "description": "CLI для завантаження cursor-правил (префікс n-) у локальний репозиторій",
5
5
  "keywords": [
6
6
  "cli",
@@ -8,8 +8,6 @@ docgen:
8
8
  score: 100
9
9
  ---
10
10
 
11
- ## Огляд
12
-
13
11
  Модуль перевіряє стан проєкту, валідуючи конфігураційні файли (`settings.json`, `hooks.json`, `settings.local.json`) та перевіряючи наявність структур для документації (adr.mdc). Перевірка включає перевірку наявності необхідних елементів, при цьому шляхи `.git` свідомо ігноруються.
14
12
 
15
13
  ## Поведінка
@@ -0,0 +1,25 @@
1
+ ---
2
+ type: JS Module
3
+ title: fix-layout.mjs
4
+ resource: npm/rules/bun/js/fix-layout.mjs
5
+ docgen:
6
+ crc: 168821f1
7
+ model: omlx/gemma-4-e4b-it-OptiQ-4bit
8
+ score: 100
9
+ ---
10
+
11
+ ## Огляд
12
+
13
+ Файл T0-autofix паттерни для `bun/js/layout.mjs` детермінують FS-виправлення, які видаляють заборонені файли залежностей (наприклад, package-lock.json), створюють відсутній bunfig.toml та рекурсивно видаляють каталог .yarn. Ці виправлення спираються на конфіги, зокрема package-lock.json.
14
+
15
+ ## Поведінка
16
+
17
+ patterns
18
+
19
+ 1. Перевіряє вивід на наявність повідомлення про знайдений заборонений файл. Якщо знайдено, ідентифікує всі заборонені файли. Для кожного ідентифікованого файлу, якщо він існує, видаляє його. Повертає результат, що вказує на успішне видалення файлів або відсутність відповідності.
20
+ 2. Перевіряє вивід на наявність повідомлення про відсутність `bunfig.toml`. Якщо повідомлення знайдено, і якщо файл `bunfig.toml` не існує, створює його з базовим вмістом. Повертає результат, що вказує на успішне створення файлу або на те, що він вже існує.
21
+ 3. Перевіряє вивід на наявність повідомлення про знайдену директорію `.yarn`. Якщо повідомлення знайдено, і якщо директорія `.yarn` існує, рекурсивно видаляє її. Повертає результат, що вказує на успішне видалення директорії або на її відсутність.
22
+
23
+ ## Гарантії поведінки
24
+
25
+ - (специфічних машинно-виведених гарантій немає)
@@ -0,0 +1,55 @@
1
+ /**
2
+ * T0-autofix паттерни для `bun/js/layout.mjs` — детерміновані FS-виправлення
3
+ * заборонених файлів (package-lock.json, yarn.lock тощо), відсутнього bunfig.toml
4
+ * та каталогу .yarn без звернення до LLM.
5
+ */
6
+ import { existsSync, rmSync, writeFileSync } from 'node:fs'
7
+ import { join } from 'node:path'
8
+
9
+ const FORBIDDEN_FILE_RE = /Знайдено заборонений файл: \S+/
10
+ const FORBIDDEN_FILE_MATCH_ALL_RE = /Знайдено заборонений файл: (\S+)/g
11
+
12
+ /** @type {import('../../../scripts/lib/fix/discover-t0-patterns.mjs').T0Pattern[]} */
13
+ export const patterns = [
14
+ {
15
+ id: 'rm-forbidden-file',
16
+ test: out => FORBIDDEN_FILE_RE.test(out),
17
+ apply: (out, cwd) => {
18
+ const matches = [...out.matchAll(FORBIDDEN_FILE_MATCH_ALL_RE)]
19
+ if (matches.length === 0) return { ok: false, action: 'no match' }
20
+
21
+ const removed = []
22
+ for (const m of matches) {
23
+ const filePath = join(cwd, m[1])
24
+ if (existsSync(filePath)) {
25
+ rmSync(filePath, { force: true })
26
+ removed.push(m[1])
27
+ }
28
+ }
29
+ if (removed.length === 0) return { ok: false, action: 'файлів не знайдено' }
30
+ return { ok: true, action: `видалено: ${removed.join(', ')}` }
31
+ }
32
+ },
33
+
34
+ {
35
+ id: 'bun-bunfig-create',
36
+ test: out => /Відсутній bunfig\.toml/.test(out),
37
+ apply: (_out, cwd) => {
38
+ const target = join(cwd, 'bunfig.toml')
39
+ if (existsSync(target)) return { ok: false, action: 'bunfig.toml вже існує' }
40
+ writeFileSync(target, '[install]\nlinker = "hoisted"\n', 'utf8')
41
+ return { ok: true, action: 'створено bunfig.toml' }
42
+ }
43
+ },
44
+
45
+ {
46
+ id: 'bun-yarn-dir-remove',
47
+ test: out => /Знайдено директорію \.yarn/.test(out),
48
+ apply: (_out, cwd) => {
49
+ const target = join(cwd, '.yarn')
50
+ if (!existsSync(target)) return { ok: false, action: '.yarn не знайдено' }
51
+ rmSync(target, { recursive: true, force: true })
52
+ return { ok: true, action: 'видалено .yarn/' }
53
+ }
54
+ }
55
+ ]
@@ -8,8 +8,6 @@ docgen:
8
8
  score: 95
9
9
  ---
10
10
 
11
- ## Огляд
12
-
13
11
  Модуль сканує монорепозиторій, ідентифікує проєкти та порівнює їхні версії з даними, отриманими з https://pypi.org/pypi/, для верифікації відповідності версій. Для проєктів, що не призначені для публікації, виконуються локальні перевірки на відповідність файлу `CHANGELOG.md` конфігурації, визначеній у res.json.
14
12
 
15
13
  ## Поведінка
@@ -19,18 +17,18 @@ docgen:
19
17
  3. `check` знаходить усі кореневі каталоги проєктів у монорепозиторії.
20
18
  4. `check` класифікує знайдені проєкти на ті, що можуть бути опубліковані в реєстрі, та ті, що є локальними.
21
19
  5. Для кожного проєкту, що може бути опублікованим, `check` перевіряє його відповідність вимогам:
22
- а. Перевіряє наявність файлу `CHANGELOG.md`.
23
- б. Перевіряє базовий формат `CHANGELOG.md` на наявність заголовка `# Changelog`.
24
- в. Якщо проєкт має поле `version` у маніфесті, `check` порівнює його з опублікованою версією, отриманою через мережевий запит до https://pypi.org/pypi/ або `npm view`.
25
- г. Якщо версія у проєкті випереджає опубліковану, `check` повідомляє про заборонений ручний bump.
26
- д. Якщо версія у проєкті відстає від опублікованої, `check` повідомляє про відставання локальної копії від реєстру.
27
- е. Якщо версії збігаються, `check` перевіряє, чи є незрелі зміни у проєкті відносно базового релізу.
28
- ж. Якщо проєкт має незрелі зміни, `check` перевіряє наявність change-файлу. Якщо його немає, `check` або повідомляє про необхідність створити його (якщо не в режимі autofix), або автоматично створює його та додає до індексу.
20
+ а. Перевіряє наявність файлу `CHANGELOG.md`.
21
+ б. Перевіряє базовий формат `CHANGELOG.md` на наявність заголовка `# Changelog`.
22
+ в. Якщо проєкт має поле `version` у маніфесті, `check` порівнює його з опублікованою версією, отриманою через мережевий запит до https://pypi.org/pypi/ або `npm view`.
23
+ г. Якщо версія у проєкті випереджає опубліковану, `check` повідомляє про заборонений ручний bump.
24
+ д. Якщо версія у проєкті відстає від опублікованої, `check` повідомляє про відставання локальної копії від реєстру.
25
+ е. Якщо версії збігаються, `check` перевіряє, чи є незрелі зміни у проєкті відносно базового релізу.
26
+ ж. Якщо проєкт має незрелі зміни, `check` перевіряє наявність change-файлу. Якщо його немає, `check` або повідомляє про необхідність створити його (якщо не в режимі autofix), або автоматично створює його та додає до індексу.
29
27
  6. `check` виконує локальні перевірки для проєктів, які не призначені для публікації:
30
- а. Для кожного локального проєкту `check` перевіряє наявність файлу `CHANGELOG.md` та його формат.
31
- б. `check` визначає точку порівняння (базу) на основі поточної гілки.
32
- в. `check` перевіряє, чи є релевантні зміни у проєкті відносно цієї бази.
33
- г. Якщо зміни є, `check` перевіряє наявність change-файлу. Якщо його немає, `check` або повідомляє про необхідність створити його (якщо не в режимі autofix), або автоматично створює його та додає до індексу.
28
+ а. Для кожного локального проєкту `check` перевіряє наявність файлу `CHANGELOG.md` та його формат.
29
+ б. `check` визначає точку порівняння (базу) на основі поточної гілки.
30
+ в. `check` перевіряє, чи є релевантні зміни у проєкті відносно цієї бази.
31
+ г. Якщо зміни є, `check` перевіряє наявність change-файлу. Якщо його немає, `check` або повідомляє про необхідність створити його (якщо не в режимі autofix), або автоматично створює його та додає до індексу.
34
32
  7. `check` повертає кінцевий код завершення, що відображає результати всіх перевірок.
35
33
 
36
34
  ## Гарантії поведінки
@@ -0,0 +1,27 @@
1
+ ---
2
+ type: JS Module
3
+ title: fix-consistency.mjs
4
+ resource: npm/rules/changelog/js/fix-consistency.mjs
5
+ docgen:
6
+ crc: f8727498
7
+ model: omlx/gemma-4-e4b-it-OptiQ-4bit
8
+ score: 100
9
+ ---
10
+
11
+ ## Огляд
12
+
13
+ Створює change-файл для воркспейсів у `changelog/js/consistency.mjs`, коли відсутній відповідний файл. Опис change-файлу береться з суб'єкта останнього git-коміту, а рівень зміни (`bump`) завжди встановлюється як `patch`.
14
+
15
+ ## Поведінка
16
+
17
+ 1. Визначає шаблони для автоматичного виправлення.
18
+ 2. `patterns` містить один шаблон, який перевіряє наявність повідомлення про відсутність change-файлу.
19
+ 3. Якщо шаблон спрацьовує, він виявляє всі воркспейси, які потребують створення change-файлу.
20
+ 4. Визначає опис для change-файлу на основі суб'єкта останнього git-коміту в корені репозиторію. Якщо суб'єкт відсутній, використовується зарезервоване повідомлення.
21
+ 5. Для кожного виявленого воркспейсу створюється change-файл з рівнем `patch` та розділом `Changed`, використовуючи визначений опис.
22
+ 6. Повертає результат, що вказує на успішне створення change-файлів для відповідних воркспейсів.
23
+
24
+ ## Гарантії поведінки
25
+
26
+ - Read-only: не виконує операцій запису (ФС/БД).
27
+ - Перехоплює помилки і не пропускає винятків назовні (fail-safe).
@@ -6,6 +6,6 @@ resource: npm/rules/changelog/js/
6
6
 
7
7
  # npm/rules/changelog/js
8
8
 
9
- | Файл | Тип |
10
- |---|---|
9
+ | Файл | Тип |
10
+ | --------------------------------- | --------- |
11
11
  | [consistency.mjs](consistency.md) | JS Module |
@@ -0,0 +1,50 @@
1
+ /**
2
+ * T0-autofix для `changelog/js/consistency.mjs` — детерміноване створення
3
+ * change-файлу для воркспейсів з релевантними змінами без change-файлу.
4
+ * Subject останнього git-коміту стає описом; bump завжди `patch`.
5
+ */
6
+ import { spawnSync } from 'node:child_process'
7
+ import { join } from 'node:path'
8
+
9
+ import { writeChange } from '../../release/change.mjs'
10
+
11
+ const MISSING_CHANGE_RE = /є релевантні зміни, але немає change-файлу/
12
+ const MISSING_CHANGE_MATCH_ALL_RE = /(?:^|\s)([\w./@-]+): є релевантні зміни, але немає change-файлу/gm
13
+
14
+ const CHANGE_BUMP = 'patch'
15
+ const CHANGE_SECTION = 'Changed'
16
+ const CHANGE_FALLBACK_MESSAGE = 'оновлення'
17
+
18
+ /**
19
+ * @param {string} cwd корінь репозиторію
20
+ * @returns {string} непорожній опис
21
+ */
22
+ function autoChangeMessage(cwd) {
23
+ const r = spawnSync('git', ['log', '-1', '--format=%s'], { cwd, encoding: 'utf8' })
24
+ const subject = r.status === 0 ? (r.stdout ?? '').trim() : ''
25
+ return subject || CHANGE_FALLBACK_MESSAGE
26
+ }
27
+
28
+ /** @type {import('../../../scripts/lib/fix/discover-t0-patterns.mjs').T0Pattern[]} */
29
+ export const patterns = [
30
+ {
31
+ id: 'changelog-create-change-file',
32
+ test: out => MISSING_CHANGE_RE.test(out),
33
+ apply: async (out, cwd) => {
34
+ const workspaces = Array.from(out.matchAll(MISSING_CHANGE_MATCH_ALL_RE), m => m[1])
35
+ if (workspaces.length === 0) return { ok: false, action: 'no match' }
36
+
37
+ const message = autoChangeMessage(cwd)
38
+ const created = []
39
+ for (const ws of workspaces) {
40
+ try {
41
+ const rel = await writeChange({ bump: CHANGE_BUMP, section: CHANGE_SECTION, message, ws, cwd })
42
+ created.push(ws === '.' ? rel : join(ws, rel))
43
+ } catch (error) {
44
+ return { ok: false, action: `writeChange ${ws}: ${error.message}` }
45
+ }
46
+ }
47
+ return { ok: true, action: `створено change-файл (${CHANGE_BUMP}/${CHANGE_SECTION}): ${created.join(', ')}` }
48
+ }
49
+ }
50
+ ]
@@ -0,0 +1,21 @@
1
+ ---
2
+ type: JS Module
3
+ title: fix-vscode_extensions.mjs
4
+ resource: npm/rules/ci4/policy/vscode_extensions/fix-vscode_extensions.mjs
5
+ docgen:
6
+ crc: 319883fc
7
+ model: omlx/gemma-4-e4b-it-OptiQ-4bit
8
+ score: 100
9
+ ---
10
+
11
+ ## Огляд
12
+
13
+ Цей файл відповідає за завантаження шаблонів, необхідних для функціонування розширення VS Code.
14
+
15
+ ## Поведінка
16
+
17
+ 1. Імпортує шаблони для виправлення розширень VS Code з іншого скрипта.
18
+
19
+ ## Гарантії поведінки
20
+
21
+ - Read-only: не виконує операцій запису (ФС/БД).
@@ -0,0 +1 @@
1
+ export { patterns } from '../../../../scripts/lib/fix/vscode-ext-add.mjs'
@@ -0,0 +1,22 @@
1
+ ---
2
+ type: JS Module
3
+ title: fix-vscode_extensions.mjs
4
+ resource: npm/rules/ga/policy/vscode_extensions/fix-vscode_extensions.mjs
5
+ docgen:
6
+ crc: 319883fc
7
+ model: omlx/gemma-4-e4b-it-OptiQ-4bit
8
+ score: 100
9
+ ---
10
+
11
+ ## Огляд
12
+
13
+ Цей файл реалізує застосування шаблонів для форматування розширень VS Code. Він застосовує правила форматування, використовуючи імпортовані шаблони.
14
+
15
+ ## Поведінка
16
+
17
+ 1. Імпортує шаблони для виправлення розширень VS Code.
18
+ 2. Використовує імпортовані шаблони для виконання логіки виправлення розширень VS Code.
19
+
20
+ ## Гарантії поведінки
21
+
22
+ - Read-only: не виконує операцій запису (ФС/БД).
@@ -0,0 +1 @@
1
+ export { patterns } from '../../../../scripts/lib/fix/vscode-ext-add.mjs'
@@ -127,6 +127,21 @@ deny contains msg if {
127
127
  msg := sprintf(setup_bun_no_checkout_template, [job_id])
128
128
  }
129
129
 
130
+ # ── deny: actions/checkout без persist-credentials: false ─────────────────
131
+ #
132
+ # `persist-credentials: false` запобігає кешуванню git-токена після checkout,
133
+ # що є обов'язковою вимогою безпеки (ga.mdc).
134
+
135
+ deny contains msg if {
136
+ some _job_id, job in jobs
137
+ some step in object.get(job, "steps", [])
138
+ uses := object.get(step, "uses", "")
139
+ startswith(uses, "actions/checkout@")
140
+ creds := object.get(object.get(step, "with", {}), "persist-credentials", true)
141
+ creds != false
142
+ msg := sprintf("jobs.%s: actions/checkout@v6 потребує `with: persist-credentials: false` (ga.mdc)", [_job_id])
143
+ }
144
+
130
145
  # ── deny: concurrency блок ─────────────────────────────────────────────────
131
146
  #
132
147
  # Дублює окремі per-workflow перевірки для clean-ga-workflows / clean-merged-branch /
@@ -0,0 +1,21 @@
1
+ ---
2
+ type: JS Module
3
+ title: fix-vscode_extensions.mjs
4
+ resource: npm/rules/graphql/policy/vscode_extensions/fix-vscode_extensions.mjs
5
+ docgen:
6
+ crc: 319883fc
7
+ model: omlx/gemma-4-e4b-it-OptiQ-4bit
8
+ score: 100
9
+ ---
10
+
11
+ ## Огляд
12
+
13
+ Завантажує шаблони, необхідні для функціонування розширення VS Code.
14
+
15
+ ## Поведінка
16
+
17
+ 1. Імпортує шаблони для виправлення розширень VS Code з іншого скрипта.
18
+
19
+ ## Гарантії поведінки
20
+
21
+ - Read-only: не виконує операцій запису (ФС/БД).
@@ -0,0 +1 @@
1
+ export { patterns } from '../../../../scripts/lib/fix/vscode-ext-add.mjs'
@@ -3,26 +3,28 @@ type: JS Module
3
3
  title: dep-policy.mjs
4
4
  resource: npm/rules/js/js/dep-policy.mjs
5
5
  docgen:
6
- crc: 020620cb
6
+ crc: a2417b44
7
7
  model: omlx/gemma-4-e4b-it-OptiQ-4bit
8
8
  score: 100
9
9
  ---
10
10
 
11
- Модуль сканує файли з розширеннями JS/TS у проєкті. Він перевіряє, чи не містять ці файли імпортів, заборонених відповідно до політики (dep-policy.mdc). Модуль виконує перевірку у режимі лише для читання. У разі виявлення порушень, він реєструє їх у звіті. Модуль перехоплює всі можливі помилки (fail-safe) і не генерує винятків назовні. Результат роботи відображається через код виходу, що інформує про статус перевірки (js.mdc).
11
+ ## Огляд
12
+
13
+ Модуль аналізує вміст файлів з розширеннями JS/TS у проєкті. Він перевіряє, чи містять ці файли імпорти, які заборонені відповідно до політики, визначеної в (dep-policy.mdc). При виявленні заборонених специфікаторів, модуль реєструє помилку у звіті та надає рекомендацію щодо заміни, згідно з (js.mdc). Модуль перехоплює всі внутрішні помилки під час сканування, забезпечуючи безпечну роботу.
12
14
 
13
15
  ## Поведінка
14
16
 
15
17
  1. Ініціалізує звітність.
16
18
  2. Визначає кореневу директорію проєкту.
17
- 3. Завантажує списки шляхів, які слід ігнорувати.
18
- 4. Збирає список усіх файлів з розширеннями JS/TS у кореневій директорії, ігноруючи визначені шляхи.
19
- 5. Для кожного зібраного файлу:
19
+ 3. Зчитує списки шляхів, які слід ігнорувати.
20
+ 4. Знаходить усі файли з розширеннями JS/TS у кореневій директорії, дотримуючись списку ігнорування.
21
+ 5. Для кожного знайденого файлу:
20
22
  а. Зчитує вміст файлу.
21
- б. Витягує з вмісту всі імпортовані специфікатори (статичні, динамічні та через `require`).
22
- в. Для кожного витягнутого специфікатора перевіряє, чи він є забороненим відповідно до політики (dep-policy.mdc).
23
- г. Якщо специфікатор заборонений, реєструє помилку у звіті, вказуючи шлях до файлу та заборонений імпорт. Збільшує лічильник порушень.
24
- 6. Якщо порушень не знайдено, реєструє повідомлення про успішну перевірку (js.mdc).
25
- 7. Повертає код виходу звіту.
23
+ б. Витягує всі імпортовані специфікатори з файлу.
24
+ в. Перевіряє кожен витягнутий специфікатор на наявність у списку заборонених специфікаторів (dep-policy.mdc).
25
+ г. Якщо специфікатор заборонений, реєструє помилку у звіті, вказуючи відносний шлях до файлу та підказку про заміну (js.mdc).
26
+ 6. Якщо жодних порушень не знайдено, реєструє успішне повідомлення про перевірку.
27
+ 7. Повертає код виходу з репортера.
26
28
 
27
29
  ## Публічний API
28
30
 
@@ -0,0 +1,22 @@
1
+ ---
2
+ type: JS Module
3
+ title: fix-vscode_extensions.mjs
4
+ resource: npm/rules/js/policy/vscode_extensions/fix-vscode_extensions.mjs
5
+ docgen:
6
+ crc: 319883fc
7
+ model: omlx/gemma-4-e4b-it-OptiQ-4bit
8
+ score: 100
9
+ ---
10
+
11
+ ## Огляд
12
+
13
+ Файл застосовує шаблони для виправлення розширень VS Code. Він виконує заміну рядків у розширеннях відповідно до імпортованих шаблонів.
14
+
15
+ ## Поведінка
16
+
17
+ 1. Імпортує шаблони для виправлення розширень VS Code.
18
+ 2. Використовує імпортовані шаблони для виконання логіки виправлення розширень VS Code.
19
+
20
+ ## Гарантії поведінки
21
+
22
+ - Read-only: не виконує операцій запису (ФС/БД).
@@ -0,0 +1 @@
1
+ export { patterns } from '../../../../scripts/lib/fix/vscode-ext-add.mjs'
@@ -0,0 +1,25 @@
1
+ ---
2
+ type: JS Module
3
+ title: fix-runtime.mjs
4
+ resource: npm/rules/js-run/js/fix-runtime.mjs
5
+ docgen:
6
+ crc: d3b1824f
7
+ model: omlx/gemma-4-e4b-it-OptiQ-4bit
8
+ score: 100
9
+ ---
10
+
11
+ ## Огляд
12
+
13
+ Детерміновано створює канонічний `jsconfig.json` у каталогах `src/` бекенд-пакетів, якщо він відсутній. Конфігурація береться з `jsconfig.json.snippet.json` (єдине джерело істини) і застосовується через публічні функції `patterns`.
14
+
15
+ ## Поведінка
16
+
17
+ 1. `patterns` надає набір правил для автоматичного виправлення.
18
+ 2. Кожне правило перевіряє, чи відсутній `jsconfig.json` у каталогах `src/` бекенд-пакетів, якщо вони існують.
19
+ 3. Якщо правило спрацьовує, воно зчитує канонічне вміст `jsconfig.json` з `policy/jsconfig/template/jsconfig.json.snippet.json`.
20
+ 4. Для кожного знайденого каталогу `src/`, якщо `jsconfig.json` відсутній, він створюється з канонічним вмістом.
21
+ 5. `patterns` повертає результат, що вказує на успішне створення файлів або на відсутність необхідних змін.
22
+
23
+ ## Гарантії поведінки
24
+
25
+ - (специфічних машинно-виведених гарантій немає)
@@ -0,0 +1,41 @@
1
+ /**
2
+ * T0-autofix для `js-run/js/runtime.mjs` — детерміноване створення канонічного
3
+ * `jsconfig.json` у backend-пакетах із `src/` де він відсутній. Канон читається
4
+ * з `policy/jsconfig/template/jsconfig.json.snippet.json` (єдине джерело істини).
5
+ */
6
+ import { existsSync, readFileSync, writeFileSync } from 'node:fs'
7
+ import { join } from 'node:path'
8
+ import { fileURLToPath } from 'node:url'
9
+
10
+ const JSCONFIG_MISSING_RE = /є каталог src\/, але немає jsconfig\.json/
11
+ const JSCONFIG_MISSING_MATCH_ALL_RE = /\[([^\]]+)\] є каталог src\/, але немає jsconfig\.json/gu
12
+
13
+ const JSCONFIG_CONTENT =
14
+ readFileSync(
15
+ fileURLToPath(new URL('../policy/jsconfig/template/jsconfig.json.snippet.json', import.meta.url)),
16
+ 'utf8'
17
+ ).trimEnd() + '\n'
18
+
19
+ /** @type {import('../../../scripts/lib/fix/discover-t0-patterns.mjs').T0Pattern[]} */
20
+ export const patterns = [
21
+ {
22
+ id: 'js-run-jsconfig-create',
23
+ test: out => JSCONFIG_MISSING_RE.test(out),
24
+ apply: (out, cwd) => {
25
+ const matches = [...out.matchAll(JSCONFIG_MISSING_MATCH_ALL_RE)]
26
+ if (matches.length === 0) return { ok: false, action: 'no match' }
27
+
28
+ const created = []
29
+ for (const m of matches) {
30
+ const ws = m[1]
31
+ const target = join(cwd, ws, 'jsconfig.json')
32
+ if (!existsSync(target)) {
33
+ writeFileSync(target, JSCONFIG_CONTENT, 'utf8')
34
+ created.push(ws)
35
+ }
36
+ }
37
+ if (created.length === 0) return { ok: false, action: 'jsconfig.json вже існує в усіх воркспейсах' }
38
+ return { ok: true, action: `створено jsconfig.json: ${created.join(', ')}` }
39
+ }
40
+ }
41
+ ]
@@ -0,0 +1,57 @@
1
+ # Перевірка `.github/workflows/lint-k8s.yml` (k8s.mdc).
2
+ #
3
+ # Канон надходить через --data: { "template": { "snippet": ... } }
4
+ # Структура --data сформована з template/lint-k8s.yml.snippet.yml.
5
+ # Перевіряємо (drift-safe — усе ведеться з template, без inline-літералів):
6
+ # - кожен `uses` з template: actions/checkout@v6, setup-bun-deps;
7
+ # - кожен `run` з template (як substring): install kubeconform, kubescape,
8
+ # n-cursor lint k8s --read-only.
9
+ # Універсальні workflow-перевірки (name, concurrency, branches,
10
+ # persist-credentials) — у `ga.workflow_common`.
11
+ package k8s.lint_k8s_yml
12
+
13
+ import rego.v1
14
+
15
+ # Усі `uses` з канону workflow (по всіх job'ах template).
16
+ expected_uses contains u if {
17
+ some job in data.template.snippet.jobs
18
+ some step in job.steps
19
+ u := object.get(step, "uses", "")
20
+ u != ""
21
+ }
22
+
23
+ # Усі `uses` з input workflow.
24
+ actual_uses contains u if {
25
+ some job in object.get(input, "jobs", {})
26
+ some step in object.get(job, "steps", [])
27
+ u := object.get(step, "uses", "")
28
+ u != ""
29
+ }
30
+
31
+ # Конкатенація всіх `run`-кроків з input workflow.
32
+ all_run_text := concat("\n", [run_text |
33
+ some job in object.get(input, "jobs", {})
34
+ some step in object.get(job, "steps", [])
35
+ run_text := step_run_to_text(step)
36
+ ])
37
+
38
+ deny contains msg if {
39
+ some required_use in expected_uses
40
+ not required_use in actual_uses
41
+ msg := sprintf("lint-k8s.yml: відсутній step з `uses: %s` (k8s.mdc)", [required_use])
42
+ }
43
+
44
+ deny contains msg if {
45
+ some job in data.template.snippet.jobs
46
+ some step in job.steps
47
+ expected_run := object.get(step, "run", "")
48
+ expected_run != ""
49
+ not contains(all_run_text, expected_run)
50
+ msg := sprintf("lint-k8s.yml: жоден крок run не містить %q (k8s.mdc)", [expected_run])
51
+ }
52
+
53
+ step_run_to_text(step) := step.run if is_string(step.run)
54
+
55
+ else := concat("\n", [s | some s in step.run]) if is_array(step.run)
56
+
57
+ else := ""