@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.
- package/CHANGELOG.md +12 -0
- package/bin/n-cursor.js +9 -27
- package/package.json +1 -1
- package/rules/adr/js/docs/hooks.md +0 -2
- package/rules/bun/js/docs/fix-layout.md +25 -0
- package/rules/bun/js/fix-layout.mjs +55 -0
- package/rules/changelog/js/docs/consistency.md +11 -13
- package/rules/changelog/js/docs/fix-consistency.md +27 -0
- package/rules/changelog/js/docs/index.md +2 -2
- package/rules/changelog/js/fix-consistency.mjs +50 -0
- package/rules/ci4/policy/vscode_extensions/docs/fix-vscode_extensions.md +21 -0
- package/rules/ci4/policy/vscode_extensions/fix-vscode_extensions.mjs +1 -0
- package/rules/ga/policy/vscode_extensions/docs/fix-vscode_extensions.md +22 -0
- package/rules/ga/policy/vscode_extensions/fix-vscode_extensions.mjs +1 -0
- package/rules/ga/policy/workflow_common/workflow_common.rego +15 -0
- package/rules/graphql/policy/vscode_extensions/docs/fix-vscode_extensions.md +21 -0
- package/rules/graphql/policy/vscode_extensions/fix-vscode_extensions.mjs +1 -0
- package/rules/js/js/docs/dep-policy.md +12 -10
- package/rules/js/policy/vscode_extensions/docs/fix-vscode_extensions.md +22 -0
- package/rules/js/policy/vscode_extensions/fix-vscode_extensions.mjs +1 -0
- package/rules/js-run/js/docs/fix-runtime.md +25 -0
- package/rules/js-run/js/fix-runtime.mjs +41 -0
- package/rules/k8s/policy/lint_k8s_yml/lint_k8s_yml.rego +57 -0
- package/rules/k8s/policy/lint_k8s_yml/target.json +4 -0
- package/rules/k8s/policy/lint_k8s_yml/template/lint-k8s.yml.snippet.yml +43 -0
- package/rules/nginx-default-tpl/policy/vscode_extensions/docs/fix-vscode_extensions.md +21 -0
- package/rules/nginx-default-tpl/policy/vscode_extensions/fix-vscode_extensions.mjs +1 -0
- package/rules/rego/policy/vscode_extensions/docs/fix-vscode_extensions.md +22 -0
- package/rules/rego/policy/vscode_extensions/fix-vscode_extensions.mjs +1 -0
- package/rules/rust/policy/vscode_extensions/docs/fix-vscode_extensions.md +22 -0
- package/rules/rust/policy/vscode_extensions/fix-vscode_extensions.mjs +1 -0
- package/rules/style/js/docs/fix-tooling.md +29 -0
- package/rules/style/js/fix-tooling.mjs +46 -0
- package/rules/style/policy/vscode_extensions/docs/fix-vscode_extensions.md +21 -0
- package/rules/style/policy/vscode_extensions/fix-vscode_extensions.mjs +1 -0
- package/rules/tauri/policy/vscode_extensions/docs/fix-vscode_extensions.md +21 -0
- package/rules/tauri/policy/vscode_extensions/fix-vscode_extensions.mjs +1 -0
- package/rules/text/policy/vscode_extensions/docs/fix-vscode_extensions.md +21 -0
- package/rules/text/policy/vscode_extensions/fix-vscode_extensions.mjs +1 -0
- package/rules/vue/js/docs/packages.md +0 -2
- package/scripts/docs/index.md +0 -2
- package/scripts/lib/discover-checkable-rules.mjs +1 -0
- package/scripts/lib/docs/discover-checkable-rules.md +13 -155
- package/scripts/lib/fix/discover-t0-patterns.mjs +83 -0
- package/scripts/lib/fix/docs/discover-t0-patterns.md +37 -0
- package/scripts/lib/fix/docs/llm-fix-apply.md +12 -10
- package/scripts/lib/fix/docs/llm-worker.md +6 -14
- package/scripts/lib/fix/docs/orchestrator.md +0 -2
- package/scripts/lib/fix/docs/t0.md +11 -10
- package/scripts/lib/fix/docs/vscode-ext-add.md +29 -0
- package/scripts/lib/fix/llm-fix-apply.mjs +34 -3
- package/scripts/lib/fix/llm-worker.mjs +24 -15
- package/scripts/lib/fix/t0.mjs +8 -119
- package/scripts/lib/fix/vscode-ext-add.mjs +45 -0
- package/rules/test/coverage/coverage.mjs +0 -317
- package/scripts/coverage-classify/apply.mjs +0 -67
- package/scripts/coverage-classify/cache.mjs +0 -77
- package/scripts/coverage-classify/docs/apply.md +0 -206
- package/scripts/coverage-classify/docs/cache.md +0 -207
- package/scripts/coverage-classify/docs/index.md +0 -14
- package/scripts/coverage-classify/docs/prompt.md +0 -136
- package/scripts/coverage-classify/docs/verdict-schema.md +0 -28
- package/scripts/coverage-classify/index.mjs +0 -114
- package/scripts/coverage-classify/prompt.mjs +0 -126
- package/scripts/coverage-classify/verdict-schema.mjs +0 -35
- package/scripts/coverage-fix-extract.mjs +0 -122
- package/scripts/coverage-fix.mjs +0 -119
- package/scripts/docs/coverage-fix-extract.md +0 -36
- package/scripts/docs/coverage-fix.md +0 -181
- package/skills/coverage-fix/SKILL.md +0 -131
- 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', '
|
|
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, а
|
|
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
|
|
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),
|
|
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
|
@@ -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
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
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
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
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).
|
|
@@ -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:
|
|
6
|
+
crc: a2417b44
|
|
7
7
|
model: omlx/gemma-4-e4b-it-OptiQ-4bit
|
|
8
8
|
score: 100
|
|
9
9
|
---
|
|
10
10
|
|
|
11
|
-
|
|
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.
|
|
19
|
-
5. Для кожного
|
|
19
|
+
3. Зчитує списки шляхів, які слід ігнорувати.
|
|
20
|
+
4. Знаходить усі файли з розширеннями JS/TS у кореневій директорії, дотримуючись списку ігнорування.
|
|
21
|
+
5. Для кожного знайденого файлу:
|
|
20
22
|
а. Зчитує вміст файлу.
|
|
21
|
-
б. Витягує
|
|
22
|
-
в.
|
|
23
|
-
г. Якщо специфікатор заборонений, реєструє помилку у звіті, вказуючи шлях до файлу та
|
|
24
|
-
6. Якщо порушень не знайдено, реєструє повідомлення про
|
|
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 := ""
|