@nitra/cursor 12.11.3 → 12.13.0
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/bin/n-cursor.js +5 -22
- package/package.json +2 -1
- package/rules/bun/docs/index.md +2 -2
- package/rules/bun/docs/main.md +7 -8
- package/rules/bun/js/docs/index.md +3 -3
- package/rules/bun/main.json +1 -1
- package/rules/bun/main.mdc +3 -1
- package/rules/bun/main.mjs +24 -12
- package/rules/changelog/js/docs/index.md +3 -3
- package/rules/ci4/main.mdc +1 -0
- package/rules/ga/main.mdc +9 -1
- package/rules/js/js/docs/index.md +5 -5
- package/rules/js/main.mdc +4 -0
- package/rules/js-run/js/docs/index.md +3 -3
- package/rules/js-run/main.mdc +3 -0
- package/rules/npm-module/main.mdc +4 -0
- package/rules/python/docs/index.md +2 -2
- package/rules/python/docs/main.md +11 -10
- package/rules/python/main.mjs +49 -1
- package/rules/rego/main.mdc +2 -0
- package/rules/rust/docs/index.md +2 -2
- package/rules/rust/docs/main.md +8 -7
- package/rules/rust/main.json +1 -1
- package/rules/rust/main.mjs +16 -3
- package/rules/security/main.mdc +2 -0
- package/rules/style/js/docs/index.md +3 -3
- package/rules/style/main.mdc +5 -1
- package/rules/test/main.mdc +2 -1
- package/rules/text/main.mdc +9 -0
- package/scripts/docs/index.md +1 -0
- package/scripts/docs/update-blue-oak.md +28 -0
- package/scripts/lib/blue-oak.mjs +45 -0
- package/scripts/lib/discover-checkable-rules.mjs +7 -14
- package/scripts/lib/docs/blue-oak.md +29 -0
- package/scripts/lib/docs/index.md +35 -35
- package/scripts/lib/docs/run-rule.md +8 -6
- package/scripts/lib/fix/discover-t0-patterns.mjs +15 -48
- package/scripts/lib/fix/docs/index.md +12 -12
- package/scripts/lib/fix/docs/llm-worker.md +13 -8
- package/scripts/lib/fix/docs/t0.md +7 -7
- package/scripts/lib/fix/llm-worker.mjs +83 -3
- package/scripts/lib/fix/t0.mjs +1 -2
- package/scripts/lib/inline-template-links.mjs +9 -17
- package/scripts/lib/list-project-rules-mdc.mjs +3 -3
- package/scripts/lib/run-rule.mjs +0 -11
- package/scripts/update-blue-oak.mjs +51 -0
- package/scripts/utils/walkDir.mjs +32 -72
- package/skills/doc-aggregate/SKILL.md +1 -0
- package/skills/publish-telegram/SKILL.md +26 -28
- package/scripts/lib/check-mdc-template-refs.mjs +0 -57
- package/scripts/lib/docs/check-mdc-template-refs.md +0 -22
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,18 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [12.13.0] - 2026-06-26
|
|
4
|
+
|
|
5
|
+
### Changed
|
|
6
|
+
|
|
7
|
+
- Заміна рекурсивного обходу файлів на використання globby для пошуку файлів
|
|
8
|
+
|
|
9
|
+
## [12.12.0] - 2026-06-25
|
|
10
|
+
|
|
11
|
+
### Changed
|
|
12
|
+
|
|
13
|
+
- Додано автоматичне додавання посилань на template-файли у main.mdc
|
|
14
|
+
- Додано підтримку Blue Oak Bronze+ для перевірки ліцензій у `bun`, `python` та `rust
|
|
15
|
+
|
|
3
16
|
## [12.11.3] - 2026-06-25
|
|
4
17
|
|
|
5
18
|
### Changed
|
package/bin/n-cursor.js
CHANGED
|
@@ -1452,11 +1452,11 @@ async function runSync() {
|
|
|
1452
1452
|
|
|
1453
1453
|
/**
|
|
1454
1454
|
* Команди, що мутують проєкт у CWD і вимагають кореня репо. `undefined`/`''` —
|
|
1455
|
-
* дефолтний sync; `check` — deprecated-alias `fix`. Решта (read-only
|
|
1455
|
+
* дефолтний sync; `check` — deprecated-alias `fix`. Решта (read-only,
|
|
1456
1456
|
* `--root`-команди `doc-aggregate`/`rename-yaml-extensions`,
|
|
1457
1457
|
* sub-лінтери) гард не зачіпає.
|
|
1458
1458
|
*/
|
|
1459
|
-
const ROOT_GUARDED_COMMANDS = new Set([undefined, '', 'lint', '
|
|
1459
|
+
const ROOT_GUARDED_COMMANDS = new Set([undefined, '', 'lint', 'release'])
|
|
1460
1460
|
|
|
1461
1461
|
/**
|
|
1462
1462
|
* Короткий опис дії для тексту root-guard помилки за іменем команди.
|
|
@@ -1472,9 +1472,6 @@ function describeRootGuardedAction(cmd) {
|
|
|
1472
1472
|
case 'lint': {
|
|
1473
1473
|
return '`lint` за замовчуванням авто-fix лінтерів (oxfmt/eslint --fix/stylelint --fix) і конформності (--full) у поточному каталозі'
|
|
1474
1474
|
}
|
|
1475
|
-
case 'change': {
|
|
1476
|
-
return '`change` пише change-файл у .changes/ поточного каталогу'
|
|
1477
|
-
}
|
|
1478
1475
|
case 'release': {
|
|
1479
1476
|
return '`release` бампає version і переписує CHANGELOG у поточному каталозі'
|
|
1480
1477
|
}
|
|
@@ -1489,10 +1486,10 @@ const [command, ...args] = process.argv.slice(2)
|
|
|
1489
1486
|
|
|
1490
1487
|
try {
|
|
1491
1488
|
// Root-guard до перших мутацій: дефолтний sync скаффолдить .cursor/.claude/CLAUDE.md/
|
|
1492
|
-
// .n-cursor.json + bun install, а lint/
|
|
1489
|
+
// .n-cursor.json + bun install, а lint/release переписують файли в CWD —
|
|
1493
1490
|
// усе це ключиться на cwd(). Запуск із піддиректорії git-репо (типово прямий
|
|
1494
1491
|
// `bun npm/bin/n-cursor.js` не з кореня) зачепив би не той каталог → STOP. Read-only та
|
|
1495
|
-
// `--root`-команди (
|
|
1492
|
+
// `--root`-команди (doc-aggregate, rename-yaml-extensions) не зачіпаємо.
|
|
1496
1493
|
if (ROOT_GUARDED_COMMANDS.has(command)) {
|
|
1497
1494
|
assertCwdIsProjectRoot(cwd(), describeRootGuardedAction(command))
|
|
1498
1495
|
}
|
|
@@ -1558,12 +1555,6 @@ try {
|
|
|
1558
1555
|
|
|
1559
1556
|
break
|
|
1560
1557
|
}
|
|
1561
|
-
case 'change': {
|
|
1562
|
-
const { runChangeCli } = await import('../rules/release/change.mjs')
|
|
1563
|
-
process.exitCode = await runChangeCli(args)
|
|
1564
|
-
|
|
1565
|
-
break
|
|
1566
|
-
}
|
|
1567
1558
|
case 'release': {
|
|
1568
1559
|
const { runReleaseCli } = await import('../rules/release/release.mjs')
|
|
1569
1560
|
process.exitCode = await runReleaseCli(args)
|
|
@@ -1575,14 +1566,6 @@ try {
|
|
|
1575
1566
|
|
|
1576
1567
|
break
|
|
1577
1568
|
}
|
|
1578
|
-
case 'trace': {
|
|
1579
|
-
// n-cursor trace — наскрізна простежуваність (spec §5.4/§7): граф
|
|
1580
|
-
// ADR↔spec↔plan↔change за front-matter + флаг розривів. exit 1 на розрив.
|
|
1581
|
-
const { runTraceCli } = await import('../scripts/dispatcher/trace.mjs')
|
|
1582
|
-
process.exitCode = runTraceCli(args)
|
|
1583
|
-
|
|
1584
|
-
break
|
|
1585
|
-
}
|
|
1586
1569
|
case 'adr-normalize-local': {
|
|
1587
1570
|
// Local-backend ADR-нормалізації: викликається з .claude/hooks/normalize-decisions.sh
|
|
1588
1571
|
// як заміна single-shot LLM-виклику. Проганяє конвеєр (retrieval→edge-judge→
|
|
@@ -1601,7 +1584,7 @@ try {
|
|
|
1601
1584
|
default: {
|
|
1602
1585
|
console.error(`❌ Невідома команда: ${command}`)
|
|
1603
1586
|
console.error(
|
|
1604
|
-
` Очікується: (без аргументів) синхронізація правил, rename-yaml-extensions, hook, adr-normalize-local, lint (включно зі scope: lint ga|rego|k8s|docker|text), analyze-escalation, taze, start-check, release, skill,
|
|
1587
|
+
` Очікується: (без аргументів) синхронізація правил, rename-yaml-extensions, hook, adr-normalize-local, lint (включно зі scope: lint ga|rego|k8s|docker|text), analyze-escalation, taze, start-check, release, skill, doc-aggregate`
|
|
1605
1588
|
)
|
|
1606
1589
|
process.exitCode = 1
|
|
1607
1590
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nitra/cursor",
|
|
3
|
-
"version": "12.
|
|
3
|
+
"version": "12.13.0",
|
|
4
4
|
"description": "CLI для завантаження cursor-правил (префікс n-) у локальний репозиторій",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"cli",
|
|
@@ -54,6 +54,7 @@
|
|
|
54
54
|
},
|
|
55
55
|
"dependencies": {
|
|
56
56
|
"@7n/mt": "^0.5.1",
|
|
57
|
+
"globby": "^16.0.0",
|
|
57
58
|
"oxc-parser": "^0.137.0",
|
|
58
59
|
"picomatch": "^4.0.4",
|
|
59
60
|
"smol-toml": "^1.7.0",
|
package/rules/bun/docs/index.md
CHANGED
package/rules/bun/docs/main.md
CHANGED
|
@@ -3,26 +3,25 @@ type: JS Module
|
|
|
3
3
|
title: main.mjs
|
|
4
4
|
resource: npm/rules/bun/main.mjs
|
|
5
5
|
docgen:
|
|
6
|
-
crc:
|
|
6
|
+
crc: 18950415
|
|
7
7
|
model: omlx/gemma-4-e4b-it-OptiQ-4bit
|
|
8
|
-
score:
|
|
8
|
+
score: 100
|
|
9
9
|
---
|
|
10
10
|
|
|
11
11
|
## Огляд
|
|
12
12
|
|
|
13
|
-
Модуль
|
|
13
|
+
Модуль застосовує політики до коду та перевіряє ліцензії залежностей (bun.mdc). Функція `run` застосовує політику до коду, використовуючи кешування у межах прогону для прискорення. Функція `lint` перевіряє ліцензії npm-залежностей, спираючись на конфігурацію в .licensee.json. У режимі `fix` вона створює .licensee.json, а в режимі `readOnly` блокує виконання.
|
|
14
14
|
|
|
15
15
|
## Поведінка
|
|
16
16
|
|
|
17
|
-
run виконує
|
|
18
|
-
lint виконує перевірку ліцензій npm-залежностей,
|
|
17
|
+
run виконує перевірку, застосовуючи політику до коду, використовуючи кешування.
|
|
18
|
+
lint виконує перевірку ліцензій npm-залежностей, генеруючи `.licensee.json` у fix-режимі або відмовляючись у readOnly режимі.
|
|
19
19
|
|
|
20
20
|
## Публічний API
|
|
21
21
|
|
|
22
|
-
run —
|
|
23
|
-
lint — Інструмент для перевірки ліцензій npm-залежностей у всьому
|
|
22
|
+
run — Точка входу правила, що виконує перевірку: застосовує логіку, перевіряє відповідність політиці та посилання на маркери повідомлень (bun.mdc).
|
|
23
|
+
lint — Інструмент для перевірки ліцензій npm-залежностей у всьому репозиторії. У режимі `--full` він працює повноцінно; у режимі виправлення автоматично створює файл .licensee.json, якщо його немає.
|
|
24
24
|
|
|
25
25
|
## Гарантії поведінки
|
|
26
26
|
|
|
27
|
-
- Read-only: не виконує операцій запису (ФС/БД).
|
|
28
27
|
- Кешує результати в межах одного прогону.
|
|
@@ -6,7 +6,7 @@ resource: npm/rules/bun/js/
|
|
|
6
6
|
|
|
7
7
|
# npm/rules/bun/js
|
|
8
8
|
|
|
9
|
-
| Файл
|
|
10
|
-
|
|
9
|
+
| Файл | Тип |
|
|
10
|
+
| ------------------------------- | --------- |
|
|
11
11
|
| [fix-layout.mjs](fix-layout.md) | JS Module |
|
|
12
|
-
| [layout.mjs](layout.md)
|
|
12
|
+
| [layout.mjs](layout.md) | JS Module |
|
package/rules/bun/main.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{ "auto": { "glob": "package.json" }, "lint": "full" }
|
|
1
|
+
{ "auto": { "glob": ["package.json", ".licensee.json"] }, "lint": "full" }
|
package/rules/bun/main.mdc
CHANGED
|
@@ -5,4 +5,6 @@ alwaysApply: false
|
|
|
5
5
|
version: '2.1'
|
|
6
6
|
---
|
|
7
7
|
|
|
8
|
-
Проект використовує тільки Bun для керування залежностями та запуску скриптів.
|
|
8
|
+
Проект використовує тільки Bun для керування залежностями та запуску скриптів.
|
|
9
|
+
- [package.json.deny.json](./policy/package_json/template/package.json.deny.json)
|
|
10
|
+
- [bunfig.toml.snippet.toml](./policy/bunfig/template/bunfig.toml.snippet.toml)
|
package/rules/bun/main.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { existsSync } from 'node:fs'
|
|
1
|
+
import { existsSync, writeFileSync } from 'node:fs'
|
|
2
2
|
import { join } from 'node:path'
|
|
3
3
|
import { spawnSync } from 'node:child_process'
|
|
4
4
|
|
|
@@ -19,20 +19,32 @@ export function run(ctx) {
|
|
|
19
19
|
return runStandardRule(import.meta.dirname, ctx)
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
+
/** Дефолтний allowlist: Blue Oak bronze — дозволяє MIT/Apache/BSD/ISC, блокує GPL/AGPL/LGPL. */
|
|
23
|
+
const DEFAULT_LICENSEE_CONFIG = JSON.stringify({ licenses: { blueOak: 'bronze' }, corrections: true }, null, 2) + '\n'
|
|
24
|
+
|
|
22
25
|
/**
|
|
23
|
-
* Перевірка ліцензій npm-залежностей через `licensee`.
|
|
24
|
-
* `.licensee.json` відсутній
|
|
25
|
-
*
|
|
26
|
+
* Перевірка ліцензій npm-залежностей через `licensee`.
|
|
27
|
+
* У fix-режимі: якщо `.licensee.json` відсутній — генерує його з дефолтним allowlist
|
|
28
|
+
* (blueOak: bronze) і запускає перевірку. У readOnly (CI): відсутність файлу → fail.
|
|
26
29
|
* @param {string} [cwd] корінь проєкту
|
|
30
|
+
* @param {{ readOnly?: boolean }} [opts]
|
|
27
31
|
* @returns {number} 0 — OK, 1 — порушення
|
|
28
32
|
*/
|
|
29
|
-
function runLicenseeSteps(cwd = process.cwd()) {
|
|
33
|
+
function runLicenseeSteps(cwd = process.cwd(), opts = {}) {
|
|
34
|
+
const readOnly = opts.readOnly === true
|
|
30
35
|
const reporter = createCheckReporter()
|
|
31
36
|
const { pass, fail } = reporter
|
|
32
37
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
38
|
+
const configPath = join(cwd, '.licensee.json')
|
|
39
|
+
if (!existsSync(configPath)) {
|
|
40
|
+
if (readOnly) {
|
|
41
|
+
fail(
|
|
42
|
+
'lint-bun: licensee — немає .licensee.json; запустіть `npx @nitra/cursor fix bun` локально для генерації (bun.mdc)'
|
|
43
|
+
)
|
|
44
|
+
return reporter.getExitCode()
|
|
45
|
+
}
|
|
46
|
+
writeFileSync(configPath, DEFAULT_LICENSEE_CONFIG, 'utf8')
|
|
47
|
+
pass('lint-bun: licensee — створено .licensee.json з дефолтним allowlist (blueOak: bronze)')
|
|
36
48
|
}
|
|
37
49
|
|
|
38
50
|
const bun = resolveCmd('bun')
|
|
@@ -53,14 +65,14 @@ function runLicenseeSteps(cwd = process.cwd()) {
|
|
|
53
65
|
|
|
54
66
|
/**
|
|
55
67
|
* Оркестраторний адаптер `n-cursor lint bun`: licensee-перевірка ліцензій npm-залежностей.
|
|
56
|
-
* Whole-repo (ігнорує `_files`).
|
|
68
|
+
* Whole-repo (ігнорує `_files`). Fix-режим: auto-генерує `.licensee.json` якщо відсутній.
|
|
57
69
|
* @param {string[] | undefined} _files ігнорується
|
|
58
70
|
* @param {string} [cwd] корінь
|
|
59
|
-
* @param {{ readOnly?: boolean }} [
|
|
71
|
+
* @param {{ readOnly?: boolean }} [opts] readOnly → не мутує ФС; відсутність конфігу → fail
|
|
60
72
|
* @returns {Promise<number>} exit code
|
|
61
73
|
*/
|
|
62
|
-
export function lint(_files, cwd = process.cwd(),
|
|
63
|
-
return runStandardLint(import.meta.dirname, () => runLicenseeSteps(cwd))
|
|
74
|
+
export function lint(_files, cwd = process.cwd(), opts = {}) {
|
|
75
|
+
return runStandardLint(import.meta.dirname, () => runLicenseeSteps(cwd, opts))
|
|
64
76
|
}
|
|
65
77
|
|
|
66
78
|
if (isRunAsCli(import.meta.url)) {
|
|
@@ -6,7 +6,7 @@ resource: npm/rules/changelog/js/
|
|
|
6
6
|
|
|
7
7
|
# npm/rules/changelog/js
|
|
8
8
|
|
|
9
|
-
| Файл
|
|
10
|
-
|
|
11
|
-
| [consistency.mjs](consistency.md)
|
|
9
|
+
| Файл | Тип |
|
|
10
|
+
| ----------------------------------------- | --------- |
|
|
11
|
+
| [consistency.mjs](consistency.md) | JS Module |
|
|
12
12
|
| [fix-consistency.mjs](fix-consistency.md) | JS Module |
|
package/rules/ci4/main.mdc
CHANGED
|
@@ -372,3 +372,4 @@ Rego-перевірки, що запускаються через `conftest` у
|
|
|
372
372
|
| --------------------------- | -------------------------------------------------------------------- |
|
|
373
373
|
| `ci4.vscode_extensions` | `.vscode/extensions.json` містить `arr.marksman` у `recommendations` |
|
|
374
374
|
|
|
375
|
+
- [extensions.json.snippet.json](./policy/vscode_extensions/template/extensions.json.snippet.json)
|
package/rules/ga/main.mdc
CHANGED
|
@@ -5,4 +5,12 @@ globs: ".github/workflows/*.yml"
|
|
|
5
5
|
alwaysApply: false
|
|
6
6
|
---
|
|
7
7
|
|
|
8
|
-
Правило **ga** перевіряє структуру `.github/workflows/`, наявність обов'язкових workflow-файлів і їх відповідність канонам, а також налаштування VS Code та zizmor для роботи з GitHub Actions.
|
|
8
|
+
Правило **ga** перевіряє структуру `.github/workflows/`, наявність обов'язкових workflow-файлів і їх відповідність канонам, а також налаштування VS Code та zizmor для роботи з GitHub Actions.
|
|
9
|
+
- [settings.json.snippet.json](./policy/vscode_settings/template/settings.json.snippet.json)
|
|
10
|
+
- [git-ai.yml.snippet.yml](./policy/git_ai/template/git-ai.yml.snippet.yml)
|
|
11
|
+
- [clean-ga-workflows.yml.snippet.yml](./policy/clean_ga_workflows/template/clean-ga-workflows.yml.snippet.yml)
|
|
12
|
+
- [lint-ga.yml.snippet.yml](./policy/lint_ga/template/lint-ga.yml.snippet.yml)
|
|
13
|
+
- [zizmor.yml.snippet.yml](./policy/zizmor_yml/template/zizmor.yml.snippet.yml)
|
|
14
|
+
- [clean-merged-branch.yml.snippet.yml](./policy/clean_merged_branch/template/clean-merged-branch.yml.snippet.yml)
|
|
15
|
+
- [extensions.json.snippet.json](./policy/vscode_extensions/template/extensions.json.snippet.json)
|
|
16
|
+
- [uses-min-versions.snippet.json](./policy/workflow_common/template/uses-min-versions.snippet.json)
|
|
@@ -6,10 +6,10 @@ resource: npm/rules/js/js/
|
|
|
6
6
|
|
|
7
7
|
# npm/rules/js/js
|
|
8
8
|
|
|
9
|
-
| Файл
|
|
10
|
-
|
|
11
|
-
| [check.mjs](check.md)
|
|
12
|
-
| [dep-policy.mjs](dep-policy.md)
|
|
9
|
+
| Файл | Тип |
|
|
10
|
+
| ------------------------------------- | --------- |
|
|
11
|
+
| [check.mjs](check.md) | JS Module |
|
|
12
|
+
| [dep-policy.mjs](dep-policy.md) | JS Module |
|
|
13
13
|
| [lint-findings.mjs](lint-findings.md) | JS Module |
|
|
14
|
-
| [tooling.mjs](tooling.md)
|
|
14
|
+
| [tooling.mjs](tooling.md) | JS Module |
|
|
15
15
|
| [utils_imports.mjs](utils_imports.md) | JS Module |
|
package/rules/js/main.mdc
CHANGED
|
@@ -11,3 +11,7 @@ version: '1.30'
|
|
|
11
11
|
|
|
12
12
|
Rego-пакети у `policy/` — запускаються `npx @nitra/cursor fix js` або `conftest`:
|
|
13
13
|
|
|
14
|
+
- [lint-js.yml.snippet.yml](./policy/lint_js_yml/template/lint-js.yml.snippet.yml)
|
|
15
|
+
- [.jscpd.json.snippet.json](./policy/jscpd/template/.jscpd.json.snippet.json)
|
|
16
|
+
- [extensions.json.snippet.json](./policy/vscode_extensions/template/extensions.json.snippet.json)
|
|
17
|
+
- [package.json.snippet.json](./policy/package_json/template/package.json.snippet.json)
|
|
@@ -6,7 +6,7 @@ resource: npm/rules/js-run/js/
|
|
|
6
6
|
|
|
7
7
|
# npm/rules/js-run/js
|
|
8
8
|
|
|
9
|
-
| Файл
|
|
10
|
-
|
|
9
|
+
| Файл | Тип |
|
|
10
|
+
| --------------------------------- | --------- |
|
|
11
11
|
| [fix-runtime.mjs](fix-runtime.md) | JS Module |
|
|
12
|
-
| [runtime.mjs](runtime.md)
|
|
12
|
+
| [runtime.mjs](runtime.md) | JS Module |
|
package/rules/js-run/main.mdc
CHANGED
|
@@ -11,3 +11,6 @@ version: '1.12'
|
|
|
11
11
|
|
|
12
12
|
Rego-пакети, які запускає `npx @nitra/cursor fix js-run` / `npx @nitra/cursor check`:
|
|
13
13
|
|
|
14
|
+
- [jsconfig.json.snippet.json](./policy/jsconfig/template/jsconfig.json.snippet.json)
|
|
15
|
+
- [configmap.yaml.contains.yml](./policy/configmap/template/configmap.yaml.contains.yml)
|
|
16
|
+
- [package.json.deny.json](./policy/package_json/template/package.json.deny.json)
|
|
@@ -18,3 +18,7 @@ Bun monorepo: workspace **`npm/`**, кореневий **`package.json`**, **`.g
|
|
|
18
18
|
Rego-пакети (запускаються через `npx @nitra/cursor fix`):
|
|
19
19
|
|
|
20
20
|
- `npm_module.npm_publish_yml` — template-driven перевірка `.github/workflows/npm-publish.yml` (deep-subset: усі обовʼязкові поля й кроки з канонічного сніпету).
|
|
21
|
+
- [package.json.snippet.json](./policy/npm_package_json/template/package.json.snippet.json)
|
|
22
|
+
- [npm-publish.yml.snippet.yml](./policy/npm_publish_yml/template/npm-publish.yml.snippet.yml)
|
|
23
|
+
- [package.json.snippet.json](./policy/root_package_json/template/package.json.snippet.json)
|
|
24
|
+
- [tsconfig.emit-types.json.snippet.json](./policy/emit_types_config/template/tsconfig.emit-types.json.snippet.json)
|
|
@@ -3,29 +3,30 @@ type: JS Module
|
|
|
3
3
|
title: main.mjs
|
|
4
4
|
resource: npm/rules/python/main.mjs
|
|
5
5
|
docgen:
|
|
6
|
-
crc:
|
|
6
|
+
crc: b072766d
|
|
7
7
|
model: omlx/gemma-4-e4b-it-OptiQ-4bit
|
|
8
8
|
score: 90
|
|
9
9
|
---
|
|
10
10
|
|
|
11
11
|
## Огляд
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
Виконує послідовність кроків для валідації коду Python відповідно до правил, визначених у (python.mdc). Перед запуском інструментів перевіряє наявність `pyproject.toml` у корені; якщо він відсутній, завершує роботу з кодом 0. Якщо файл присутній, перевіряє наявність `uv` у PATH, оскільки він є єдиним пакет-менеджером. Обов'язково виконує `uv lock --check` для підтвердження актуальності lock-файлу та `uv sync --frozen` для синхронізації середовища з `uv.lock` (див. https://docs.astral.sh/uv/). Опційні лінтери запускаються лише за умови їх доступності через `uv run`. При використанні `ruff` застосовується автоматичне виправлення (`auto-fix`), що модифікує робоче дерево. Усі операції виконуються з механізмом перехоплення помилок (fail-safe), запобігаючи викиданню винятків назовні.
|
|
14
14
|
|
|
15
15
|
## Поведінка
|
|
16
16
|
|
|
17
|
-
run виконує стандартну перевірку
|
|
18
|
-
runLintPythonSteps виконує
|
|
19
|
-
runLintPython запускає
|
|
20
|
-
lint оркеструє запуск `runLintPython` для
|
|
17
|
+
run виконує стандартну перевірку на основі контексту.
|
|
18
|
+
runLintPythonSteps виконує повний цикл лінтування Python, включаючи перевірку `uv lock --check`, `uv sync --frozen` та запуск лінтерів, якщо `pyproject.toml` присутній.
|
|
19
|
+
runLintPython запускає кроки лінтування Python, використовуючи механізм серіалізації через `runStandardLint`.
|
|
20
|
+
lint оркеструє запуск `runLintPython` з опцією `readOnly` для детектних перевірок.
|
|
21
21
|
|
|
22
22
|
## Публічний API
|
|
23
23
|
|
|
24
|
-
run —
|
|
25
|
-
runLintPythonSteps — Виконує внутрішні етапи
|
|
26
|
-
runLintPython — Публічний інтерфейс командного рядка для запуску
|
|
27
|
-
lint —
|
|
24
|
+
run — Точка входу для виконання правил, яка перевіряє аспекти застосування (JS-занепокложення $\rightarrow$ політика $\rightarrow$ mdc-посилання).
|
|
25
|
+
runLintPythonSteps — Виконує внутрішні етапи перевірки коду Python без збереження результатів.
|
|
26
|
+
runLintPython — Публічний інтерфейс командного рядка для запуску перевірки коду Python, що забезпечує унікальність завдяки блоку блокування та аналізу стану Git-дерева.
|
|
27
|
+
lint — Адаптер, що керує запуском перевірки коду Python, делегуючи це `runLintPython`.
|
|
28
28
|
|
|
29
29
|
## Гарантії поведінки
|
|
30
30
|
|
|
31
31
|
- Read-only: не виконує операцій запису (ФС/БД).
|
|
32
|
+
- Перехоплює помилки і не пропускає винятків назовні (fail-safe).
|
package/rules/python/main.mjs
CHANGED
|
@@ -30,6 +30,7 @@ import { resolveCmd } from '../../scripts/utils/resolve-cmd.mjs'
|
|
|
30
30
|
import { runStandardLint } from '../../scripts/lib/run-standard-lint.mjs'
|
|
31
31
|
import { runRuleCli } from '../../scripts/lib/run-rule-cli.mjs'
|
|
32
32
|
import { runStandardRule } from '../../scripts/lib/run-standard-rule.mjs'
|
|
33
|
+
import { getBronzeAndAbove, isSpdxAllowed } from '../../scripts/lib/blue-oak.mjs'
|
|
33
34
|
|
|
34
35
|
/**
|
|
35
36
|
* Єдиний entrypoint правила (ADR 2026-06-21). `run()` — check-поверхня (applies → JS-concerns
|
|
@@ -112,13 +113,60 @@ export function runLintPythonSteps(cwd = process.cwd(), opts = {}) {
|
|
|
112
113
|
return runTool(label, uv, ['run', '--frozen', tool, ...args], pass, fail)
|
|
113
114
|
}
|
|
114
115
|
|
|
116
|
+
/**
|
|
117
|
+
* Перевірка ліцензій Python-залежностей через pip-licenses + Blue Oak Bronze+.
|
|
118
|
+
* Opt-in: пропускається якщо pip-licenses не встановлений у uv-середовищі.
|
|
119
|
+
* @param {string} uvPath абсолютний шлях до uv
|
|
120
|
+
* @param {string} cwdPath корінь проєкту
|
|
121
|
+
* @param {(msg: string) => void} passF
|
|
122
|
+
* @param {(msg: string) => void} failF
|
|
123
|
+
* @returns {boolean} true якщо OK або пропущено; false якщо порушення
|
|
124
|
+
*/
|
|
125
|
+
function checkPipLicenses(uvPath, cwdPath, passF, failF) {
|
|
126
|
+
if (!uvToolAvailable(uvPath, 'pip-licenses')) {
|
|
127
|
+
passF('lint-python: pip-licenses недоступний у uv-середовищі — перевірку ліцензій пропущено')
|
|
128
|
+
return true
|
|
129
|
+
}
|
|
130
|
+
const r = spawnSync(uvPath, ['run', '--frozen', 'pip-licenses', '--from=mixed', '--format=spdx-json'], {
|
|
131
|
+
cwd: cwdPath,
|
|
132
|
+
stdio: ['ignore', 'pipe', 'inherit'],
|
|
133
|
+
shell: false
|
|
134
|
+
})
|
|
135
|
+
if (r.status !== 0) {
|
|
136
|
+
failF('lint-python: pip-licenses — помилка виконання')
|
|
137
|
+
return false
|
|
138
|
+
}
|
|
139
|
+
const allowed = getBronzeAndAbove()
|
|
140
|
+
let doc
|
|
141
|
+
try {
|
|
142
|
+
doc = JSON.parse(r.stdout.toString('utf8'))
|
|
143
|
+
} catch {
|
|
144
|
+
doc = null
|
|
145
|
+
}
|
|
146
|
+
const packages = doc?.packages ?? []
|
|
147
|
+
const violations = packages.filter(pkg => {
|
|
148
|
+
const lic = pkg.licenseDeclared ?? pkg.licenseConcluded ?? 'NOASSERTION'
|
|
149
|
+
return !isSpdxAllowed(lic, allowed)
|
|
150
|
+
})
|
|
151
|
+
if (violations.length > 0) {
|
|
152
|
+
for (const pkg of violations) {
|
|
153
|
+
const lic = pkg.licenseDeclared ?? pkg.licenseConcluded ?? 'NOASSERTION'
|
|
154
|
+
process.stdout.write(` ✗ ${pkg.name}@${pkg.versionInfo ?? '?'}: ${lic}\n`)
|
|
155
|
+
}
|
|
156
|
+
failF(`lint-python: pip-licenses — ${violations.length} пакет(ів) поза Blue Oak Bronze+ (python.mdc)`)
|
|
157
|
+
return false
|
|
158
|
+
}
|
|
159
|
+
passF(`lint-python: pip-licenses — ліцензії OK (Blue Oak Bronze+, ${packages.length} пакетів)`)
|
|
160
|
+
return true
|
|
161
|
+
}
|
|
162
|
+
|
|
115
163
|
const ruffCheck = readOnly ? ['check', '.'] : ['check', '--fix', '.']
|
|
116
164
|
const ruffFormat = readOnly ? ['format', '--check', '.'] : ['format', '.']
|
|
117
165
|
if (!runOptionalUvTool('ruff', readOnly ? 'ruff check' : 'ruff check --fix', ruffCheck)) return reporter.getExitCode()
|
|
118
166
|
if (!runOptionalUvTool('ruff', readOnly ? 'ruff format --check' : 'ruff format', ruffFormat))
|
|
119
167
|
return reporter.getExitCode()
|
|
120
168
|
if (!runOptionalUvTool('mypy', 'mypy', ['.'])) return reporter.getExitCode()
|
|
121
|
-
if (!
|
|
169
|
+
if (!checkPipLicenses(uv, cwd, pass, fail)) return reporter.getExitCode()
|
|
122
170
|
|
|
123
171
|
return reporter.getExitCode()
|
|
124
172
|
}
|
package/rules/rego/main.mdc
CHANGED
|
@@ -16,3 +16,5 @@ alwaysApply: false
|
|
|
16
16
|
| `rego.vscode_extensions` | `.vscode/extensions.json` | `recommendations` містить `tsandall.opa` |
|
|
17
17
|
| `rego.vscode_settings` | `.vscode/settings.json` | `[rego]`-блок з `defaultFormatter` + `formatOnSave` |
|
|
18
18
|
|
|
19
|
+
- [settings.json.snippet.json](./policy/vscode_settings/template/settings.json.snippet.json)
|
|
20
|
+
- [extensions.json.snippet.json](./policy/vscode_extensions/template/extensions.json.snippet.json)
|
package/rules/rust/docs/index.md
CHANGED
package/rules/rust/docs/main.md
CHANGED
|
@@ -3,25 +3,26 @@ type: JS Module
|
|
|
3
3
|
title: main.mjs
|
|
4
4
|
resource: npm/rules/rust/main.mjs
|
|
5
5
|
docgen:
|
|
6
|
-
crc:
|
|
6
|
+
crc: bbddef51
|
|
7
7
|
model: omlx/gemma-4-e4b-it-OptiQ-4bit
|
|
8
8
|
score: 100
|
|
9
9
|
---
|
|
10
10
|
|
|
11
11
|
## Огляд
|
|
12
12
|
|
|
13
|
-
Модуль
|
|
13
|
+
Модуль надає інструменти для забезпечення якості коду на Rust. Він дозволяє виконати перевірку стилю за допомогою функції `lint` або запустити повну оркестрацію, що включає форматування та аналіз, за допомогою функції `run`. (rust.mdc)
|
|
14
14
|
|
|
15
15
|
## Поведінка
|
|
16
16
|
|
|
17
|
-
run виконує перевірку
|
|
18
|
-
|
|
17
|
+
run виконує стандартну перевірку для Rust-коду.
|
|
18
|
+
|
|
19
|
+
lint запускає оркестрацію перевірки Rust-коду, включаючи форматування та аналіз.
|
|
19
20
|
|
|
20
21
|
## Публічний API
|
|
21
22
|
|
|
22
|
-
run —
|
|
23
|
-
lint —
|
|
23
|
+
run — виконує основну перевірку, що включає перевірку логіки, пов'язаної з JS, політики та посиланнями MDC (rust.mdc).
|
|
24
|
+
lint — забезпечує фіксацію та виконання перевірок стилю коду (аналогічно cargo fmt/clippy) для `n-cursor lint rust`.
|
|
24
25
|
|
|
25
26
|
## Гарантії поведінки
|
|
26
27
|
|
|
27
|
-
-
|
|
28
|
+
- (специфічних машинно-виведених гарантій немає)
|
package/rules/rust/main.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{ "auto": { "glob": "**/Cargo.toml" }, "lint": "full" }
|
|
1
|
+
{ "auto": { "glob": ["**/Cargo.toml", "deny.toml"] }, "lint": "full" }
|
package/rules/rust/main.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/** @see ./docs/lint.md */
|
|
2
2
|
import { spawnSync } from 'node:child_process'
|
|
3
|
-
import { existsSync } from 'node:fs'
|
|
3
|
+
import { existsSync, writeFileSync } from 'node:fs'
|
|
4
4
|
import { join } from 'node:path'
|
|
5
5
|
|
|
6
6
|
import { createCheckReporter } from '../../scripts/lib/check-reporter.mjs'
|
|
@@ -8,6 +8,7 @@ import { runStandardLint } from '../../scripts/lib/run-standard-lint.mjs'
|
|
|
8
8
|
import { resolveCmd } from '../../scripts/utils/resolve-cmd.mjs'
|
|
9
9
|
import { isRunAsCli, runRuleCli } from '../../scripts/lib/run-rule-cli.mjs'
|
|
10
10
|
import { runStandardRule } from '../../scripts/lib/run-standard-rule.mjs'
|
|
11
|
+
import { generateDenyTomlLicenses } from '../../scripts/lib/blue-oak.mjs'
|
|
11
12
|
|
|
12
13
|
/**
|
|
13
14
|
* Єдиний entrypoint правила (ADR 2026-06-21). `run()` — check-поверхня (applies → JS-concerns
|
|
@@ -83,8 +84,20 @@ function runRustLint(cwd = process.cwd(), opts = {}) {
|
|
|
83
84
|
fail
|
|
84
85
|
)
|
|
85
86
|
|
|
86
|
-
// cargo deny check licenses
|
|
87
|
-
|
|
87
|
+
// cargo deny check licenses: fix-режим — auto-генерує deny.toml якщо відсутній;
|
|
88
|
+
// readOnly (CI) — відсутність файлу → fail.
|
|
89
|
+
const denyConfigPath = join(cwd, 'deny.toml')
|
|
90
|
+
if (!existsSync(denyConfigPath)) {
|
|
91
|
+
if (readOnly) {
|
|
92
|
+
fail(
|
|
93
|
+
'lint-rust: cargo deny — немає deny.toml; запустіть `npx @nitra/cursor fix rust` локально для генерації (rust.mdc)'
|
|
94
|
+
)
|
|
95
|
+
} else {
|
|
96
|
+
writeFileSync(denyConfigPath, generateDenyTomlLicenses(), 'utf8')
|
|
97
|
+
pass('lint-rust: cargo deny — створено deny.toml з дефолтним allowlist')
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
if (existsSync(denyConfigPath)) {
|
|
88
101
|
const hasDeny = spawnSync(cargo, ['deny', '--version'], { stdio: 'ignore', shell: false }).status === 0
|
|
89
102
|
if (hasDeny) {
|
|
90
103
|
runCargo('cargo deny check licenses', cargo, ['deny', 'check', 'licenses'], pass, fail)
|
package/rules/security/main.mdc
CHANGED
|
@@ -6,7 +6,7 @@ resource: npm/rules/style/js/
|
|
|
6
6
|
|
|
7
7
|
# npm/rules/style/js
|
|
8
8
|
|
|
9
|
-
| Файл
|
|
10
|
-
|
|
9
|
+
| Файл | Тип |
|
|
10
|
+
| --------------------------------- | --------- |
|
|
11
11
|
| [fix-tooling.mjs](fix-tooling.md) | JS Module |
|
|
12
|
-
| [tooling.mjs](tooling.md)
|
|
12
|
+
| [tooling.mjs](tooling.md) | JS Module |
|
package/rules/style/main.mdc
CHANGED
|
@@ -5,4 +5,8 @@ globs: "**/*.{css,scss,vue}"
|
|
|
5
5
|
alwaysApply: false
|
|
6
6
|
---
|
|
7
7
|
|
|
8
|
-
Правило **style** для Vue-проєктів: Quasar як стильова система, SCSS-конвенції кольорів і відступів, фікси компонентів, stylelint через `@nitra/stylelint-config`.
|
|
8
|
+
Правило **style** для Vue-проєктів: Quasar як стильова система, SCSS-конвенції кольорів і відступів, фікси компонентів, stylelint через `@nitra/stylelint-config`.
|
|
9
|
+
- [settings.json.snippet.json](./policy/vscode_settings/template/settings.json.snippet.json)
|
|
10
|
+
- [lint-style.yml.snippet.yml](./policy/lint_style_yml/template/lint-style.yml.snippet.yml)
|
|
11
|
+
- [extensions.json.snippet.json](./policy/vscode_extensions/template/extensions.json.snippet.json)
|
|
12
|
+
- [package.json.snippet.json](./policy/package_json/template/package.json.snippet.json)
|
package/rules/test/main.mdc
CHANGED
|
@@ -19,4 +19,5 @@ alwaysApply: false
|
|
|
19
19
|
|
|
20
20
|
### Multi-workspace iteration
|
|
21
21
|
|
|
22
|
-
У monorepo `n-cursor coverage` ітерує усі workspaces з власним `package.json` і агрегує метрики lcov + Stryker у єдиний `JS`-рядок `COVERAGE.md`. Workspace без тестів пропускається без помилки.
|
|
22
|
+
У monorepo `n-cursor coverage` ітерує усі workspaces з власним `package.json` і агрегує метрики lcov + Stryker у єдиний `JS`-рядок `COVERAGE.md`. Workspace без тестів пропускається без помилки.
|
|
23
|
+
- [package.json.contains.json](./policy/package_json/template/package.json.contains.json)
|
package/rules/text/main.mdc
CHANGED
|
@@ -10,3 +10,12 @@ version: '1.30'
|
|
|
10
10
|
|
|
11
11
|
Rego-пакети, що перевіряються через conftest (auto-discovered за `target.json` поряд із `.rego`):
|
|
12
12
|
|
|
13
|
+
- [settings.json.snippet.json](./policy/vscode_settings/template/settings.json.snippet.json)
|
|
14
|
+
- [.oxfmtrc.json.snippet.json](./policy/oxfmtrc/template/.oxfmtrc.json.snippet.json)
|
|
15
|
+
- [.markdownlint-cli2.jsonc.snippet.jsonc](./policy/markdownlint/template/.markdownlint-cli2.jsonc.snippet.jsonc)
|
|
16
|
+
- [.cspell.json.snippet.json](./policy/cspell/template/.cspell.json.snippet.json)
|
|
17
|
+
- [.cspell.json.deny.json](./policy/cspell/template/.cspell.json.deny.json)
|
|
18
|
+
- [.cspell.json.contains.json](./policy/cspell/template/.cspell.json.contains.json)
|
|
19
|
+
- [extensions.json.snippet.json](./policy/vscode_extensions/template/extensions.json.snippet.json)
|
|
20
|
+
- [lint-text.yml.snippet.yml](./policy/lint_text/template/lint-text.yml.snippet.yml)
|
|
21
|
+
- [package.json.deny.json](./policy/package_json/template/package.json.deny.json)
|