@nitra/cursor 12.3.2 → 12.4.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/.claude-template/hooks/capture-decisions.sh +36 -19
- package/.claude-template/hooks/lib/tooling-only.sh +16 -0
- package/CHANGELOG.md +12 -0
- package/package.json +1 -1
- package/rules/bun/bun.mdc +5 -5
- package/rules/bun/policy/package_json/package_json.rego +0 -31
- package/rules/ga/ga.mdc +2 -4
- package/rules/ga/policy/lint_ga/lint_ga.rego +2 -2
- package/rules/ga/policy/lint_ga/template/lint-ga.yml.snippet.yml +1 -1
- package/rules/js-lint/js-lint.mdc +2 -5
- package/rules/js-lint/policy/lint_js_yml/template/lint-js.yml.snippet.yml +1 -5
- package/rules/js-lint/policy/package_json/template/package.json.snippet.json +0 -3
- package/rules/lint/js/docs/orchestrate.md +11 -12
- package/rules/lint/js/orchestrate.mjs +82 -5
- package/rules/php/js/docs/index.md +1 -0
- package/rules/php/js/docs/lint.md +20 -0
- package/rules/php/js/lint.mjs +13 -0
- package/rules/php/php.mdc +1 -3
- package/rules/php/policy/lint_php_yml/template/lint-php.yml.snippet.yml +1 -1
- package/rules/python/js/docs/index.md +1 -0
- package/rules/python/js/docs/lint.md +21 -0
- package/rules/python/js/lint.mjs +14 -0
- package/rules/python/lint/docs/lint.md +15 -312
- package/rules/python/lint/lint.mjs +11 -5
- package/rules/python/meta.json +1 -1
- package/rules/python/policy/lint_python_yml/template/lint-python.yml.snippet.yml +1 -1
- package/rules/python/python.mdc +1 -3
- package/rules/rego/rego.mdc +2 -6
- package/rules/rust/js/docs/index.md +1 -0
- package/rules/rust/js/docs/lint.md +21 -0
- package/rules/rust/js/lint.mjs +67 -0
- package/rules/rust/rust.mdc +2 -4
- package/rules/security/policy/package_json/package_json.rego +0 -19
- package/rules/security/security.mdc +5 -6
- package/rules/style-lint/policy/lint_style_yml/template/lint-style.yml.snippet.yml +1 -1
- package/rules/style-lint/policy/package_json/package_json.rego +0 -10
- package/rules/style-lint/style-lint.mdc +4 -6
- package/rules/text/js/formatting.mjs +7 -31
- package/rules/text/policy/lint_text/template/lint-text.yml.snippet.yml +1 -1
- package/rules/ga/policy/package_json/package_json.rego +0 -20
- package/rules/ga/policy/package_json/target.json +0 -8
- package/rules/ga/policy/package_json/template/package.json.contains.json +0 -1
- package/rules/php/policy/package_json/package_json.rego +0 -16
- package/rules/php/policy/package_json/target.json +0 -4
- package/rules/php/policy/package_json/template/package.json.contains.json +0 -5
- package/rules/python/policy/package_json/package_json.rego +0 -16
- package/rules/python/policy/package_json/target.json +0 -4
- package/rules/python/policy/package_json/template/package.json.contains.json +0 -5
- package/rules/rego/policy/package_json/package_json.rego +0 -16
- package/rules/rego/policy/package_json/target.json +0 -5
- package/rules/rego/policy/package_json/template/package.json.snippet.json +0 -1
- package/rules/rust/policy/package_json/package_json.rego +0 -18
- package/rules/rust/policy/package_json/target.json +0 -5
- package/rules/rust/policy/package_json/template/package.json.contains.json +0 -9
- package/rules/security/policy/package_json/template/package.json.contains.json +0 -1
- package/rules/security/policy/package_json/template/package.json.snippet.json +0 -5
- package/rules/style-lint/policy/package_json/template/package.json.contains.json +0 -5
|
@@ -10,16 +10,6 @@ package style_lint.package_json
|
|
|
10
10
|
|
|
11
11
|
import rego.v1
|
|
12
12
|
|
|
13
|
-
# ── deny: substring requirements у scripts (contains) ────────────────────
|
|
14
|
-
|
|
15
|
-
deny contains msg if {
|
|
16
|
-
some script_name, needles in data.template.contains.scripts
|
|
17
|
-
actual := object.get(object.get(input, "scripts", {}), script_name, "")
|
|
18
|
-
some needle in needles
|
|
19
|
-
not contains(actual, needle)
|
|
20
|
-
msg := sprintf("package.json: scripts.%s має містити %q (style-lint.mdc)", [script_name, needle])
|
|
21
|
-
}
|
|
22
|
-
|
|
23
13
|
# ── deny: 2-level snippet walker (для stylelint.extends, якщо поле є) ────
|
|
24
14
|
|
|
25
15
|
deny contains msg if {
|
|
@@ -95,16 +95,17 @@ $white-a1: color.adjust(white, $alpha: -0.85);
|
|
|
95
95
|
|
|
96
96
|
- **Джерело правил:** перед тим як писати або суттєво змінювати **`.css`**, **`.scss`** або стилі в **`.vue`**, переглянь у корені проєкту (і в релевантних пакетах монорепо, якщо є) поле **`stylelint`** у **`package.json`** (зокрема `extends`), наявні **`.stylelintrc.*`**, **`stylelint.config.*`** та **`.stylelintignore`**. Не покладайся на «типові» правила stylelint з пам’яті — дотримуйся **проєктного** **`@nitra/stylelint-config`** і будь-яких локальних доповнень у репозиторії.
|
|
97
97
|
- **Форматування** узгоджуй з **`n-text.mdc`** (oxfmt / `.oxfmtrc.json` для css, scss тощо), щоб форматер і stylelint не суперечили один одному.
|
|
98
|
-
- **Запуск stylelint:** лише
|
|
98
|
+
- **Запуск stylelint:** лише через **`n-cursor lint style-lint`** (локально — з auto-fix; у CI — `--read-only`, нуль мутацій). Під капотом — `npx stylelint`; **не** використовуй **`bunx stylelint`**. Після змін запускай **`n-cursor lint style-lint`** і виправляй усе, що лишилось після auto-fix; за потреби — повний прогін `n-cursor lint --full`.
|
|
99
99
|
- **Не розширюй винятки:** не додавай зайві **`stylelint-disable`** без потреби; краще підлаштувати стилі під правила проєкту.
|
|
100
100
|
|
|
101
101
|
## Канон
|
|
102
102
|
|
|
103
103
|
### `package.json`
|
|
104
104
|
|
|
105
|
-
- `lint-style` (substring requirement): [package.json.contains.json](./policy/package_json/template/package.json.contains.json)
|
|
106
105
|
- `stylelint.extends`: [package.json.snippet.json](./policy/package_json/template/package.json.snippet.json)
|
|
107
106
|
|
|
107
|
+
Окремого `lint-style` скрипта немає — запуск через **`n-cursor lint style-lint`** (CI — `--read-only`).
|
|
108
|
+
|
|
108
109
|
### `.vscode/extensions.json`
|
|
109
110
|
|
|
110
111
|
- Канон `recommendations`: [extensions.json.snippet.json](./policy/vscode_extensions/template/extensions.json.snippet.json)
|
|
@@ -120,9 +121,6 @@ $white-a1: color.adjust(white, $alpha: -0.85);
|
|
|
120
121
|
**`package.json`:**
|
|
121
122
|
|
|
122
123
|
```json title="package.json"
|
|
123
|
-
"scripts": {
|
|
124
|
-
"lint-style": "npx stylelint '**/*.{css,scss,vue}' --fix",
|
|
125
|
-
},
|
|
126
124
|
"devDependencies": {
|
|
127
125
|
"@nitra/stylelint-config": "^1.4.0"
|
|
128
126
|
},
|
|
@@ -131,7 +129,7 @@ $white-a1: color.adjust(white, $alpha: -0.85);
|
|
|
131
129
|
},
|
|
132
130
|
```
|
|
133
131
|
|
|
134
|
-
Додай **`.github/workflows/lint-style.yml`** (лише **`.yml`**, **`ga.mdc`**): після **`checkout`** — локальний composite **`setup-bun-deps`**, далі `
|
|
132
|
+
Додай **`.github/workflows/lint-style.yml`** (лише **`.yml`**, **`ga.mdc`**): після **`checkout`** — локальний composite **`setup-bun-deps`**, далі `n-cursor lint style-lint --read-only` у кроці **`run`**. **Не** дублюй окремі кроки **`setup-node`** / **`oven-sh/setup-bun`** / кеш / **`npm install`**.
|
|
135
133
|
|
|
136
134
|
```yaml title=".github/workflows/lint-style.yml"
|
|
137
135
|
name: StyleLint
|
|
@@ -94,25 +94,20 @@ function checkTextConfigsExistence(passFn, failFn, cwd) {
|
|
|
94
94
|
}
|
|
95
95
|
|
|
96
96
|
/**
|
|
97
|
-
* Перевіряє
|
|
98
|
-
*
|
|
99
|
-
*
|
|
100
|
-
* `@nitra/*` гейт) — у Rego (`text.package_json`, `bun.package_json`).
|
|
97
|
+
* Перевіряє CI-workflow текстового стека: крок `n-cursor lint text --read-only` у
|
|
98
|
+
* `.github/workflows/lint-text.yml` (CI — нуль мутацій). Окремого `lint-text` скрипта в
|
|
99
|
+
* `package.json` немає — лінт через `n-cursor lint text`. Решта package.json-перевірок
|
|
100
|
+
* (Prettier-заборона, `@nitra/cspell-dict`, `@nitra/*` гейт) — у Rego (`text.package_json`, `bun.package_json`).
|
|
101
101
|
* @param {(msg: string) => void} passFn callback при успішній перевірці
|
|
102
102
|
* @param {(msg: string) => void} failFn callback при помилці
|
|
103
103
|
* @param {string} cwd корінь репозиторію
|
|
104
104
|
*/
|
|
105
|
-
async function
|
|
106
|
-
const pkgPath = join(cwd, 'package.json')
|
|
107
|
-
if (!existsSync(pkgPath)) return
|
|
108
|
-
const pkg = JSON.parse(await readFile(pkgPath, 'utf8'))
|
|
109
|
-
checkLintTextScript(pkg.scripts?.['lint-text'], passFn, failFn)
|
|
110
|
-
|
|
105
|
+
async function checkLintTextWorkflow(passFn, failFn, cwd) {
|
|
111
106
|
const lintTextWf = join(cwd, '.github/workflows/lint-text.yml')
|
|
112
107
|
if (existsSync(lintTextWf)) {
|
|
113
108
|
const wf = await readFile(lintTextWf, 'utf8')
|
|
114
109
|
const root = parseWorkflowYaml(wf)
|
|
115
|
-
const canonRun = 'n-cursor lint
|
|
110
|
+
const canonRun = 'n-cursor lint text --read-only'
|
|
116
111
|
const ok = root ? anyRunStepIncludes(root, canonRun) : wf.includes(canonRun)
|
|
117
112
|
if (ok) {
|
|
118
113
|
passFn(`lint-text.yml викликає ${canonRun}`)
|
|
@@ -124,25 +119,6 @@ async function checkPackageJsonText(passFn, failFn, cwd) {
|
|
|
124
119
|
}
|
|
125
120
|
}
|
|
126
121
|
|
|
127
|
-
/**
|
|
128
|
-
* Перевіряє скрипт lint-text: канонічний — `n-cursor lint-text` (CLI пакета `@nitra/cursor` робить
|
|
129
|
-
* `cspell` → `runShellcheckText()` → `bunx markdownlint-cli2 --fix` → `runV8rWithGlobs()`).
|
|
130
|
-
* Дозволено whitespace навколо команди.
|
|
131
|
-
* @param {unknown} lintText значення `scripts.lint-text` з package.json
|
|
132
|
-
* @param {(msg: string) => void} passFn callback при успішній перевірці
|
|
133
|
-
* @param {(msg: string) => void} failFn callback при помилці
|
|
134
|
-
*/
|
|
135
|
-
function checkLintTextScript(lintText, passFn, failFn) {
|
|
136
|
-
const lt = typeof lintText === 'string' ? lintText.trim() : ''
|
|
137
|
-
if (lt === 'n-cursor lint-text') {
|
|
138
|
-
passFn('lint-text делегує CLI n-cursor lint-text (cspell + shellcheck + markdownlint + v8r)')
|
|
139
|
-
} else {
|
|
140
|
-
failFn(
|
|
141
|
-
'package.json: lint-text має бути "n-cursor lint-text" — CLI пакета @nitra/cursor виконує cspell → shellcheck → markdownlint-cli2 → v8r (text.mdc)'
|
|
142
|
-
)
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
|
|
146
122
|
/**
|
|
147
123
|
* Перевіряє відповідність проєкту правилам text.mdc.
|
|
148
124
|
* @param {string} [cwd] корінь репозиторію
|
|
@@ -166,7 +142,7 @@ export async function check(cwd = process.cwd()) {
|
|
|
166
142
|
}
|
|
167
143
|
}
|
|
168
144
|
|
|
169
|
-
await
|
|
145
|
+
await checkLintTextWorkflow(pass, fail, cwd)
|
|
170
146
|
|
|
171
147
|
return reporter.getExitCode()
|
|
172
148
|
}
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
# Перевірка кореневого `package.json` для GitHub Actions tooling (ga.mdc).
|
|
2
|
-
#
|
|
3
|
-
# Канон надходить через --data: { "template": { "contains": ... } }
|
|
4
|
-
# Структура --data сформована з template/package.json.contains.json.
|
|
5
|
-
#
|
|
6
|
-
# Конвенція проєкту — `import rego.v1` + multi-value `deny contains msg if { … }`
|
|
7
|
-
# (.cursor/rules/conftest.mdc). Лінт — `bun run lint-rego` (regal).
|
|
8
|
-
package ga.package_json
|
|
9
|
-
|
|
10
|
-
import rego.v1
|
|
11
|
-
|
|
12
|
-
# Кожне рядкове поле з contains має містити кожен substring.
|
|
13
|
-
# Відсутність ключа → `""` → contains() = false → deny.
|
|
14
|
-
deny contains msg if {
|
|
15
|
-
some script_name, needles in data.template.contains.scripts
|
|
16
|
-
actual := object.get(object.get(input, "scripts", {}), script_name, "")
|
|
17
|
-
some needle in needles
|
|
18
|
-
not contains(actual, needle)
|
|
19
|
-
msg := sprintf("package.json: scripts.%s має містити %q (ga.mdc)", [script_name, needle])
|
|
20
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{ "scripts": { "lint-ga": ["n-cursor lint-ga"] } }
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
# Перевірка `package.json` (php.mdc).
|
|
2
|
-
#
|
|
3
|
-
# Канон надходить через --data: { "template": { "contains": ... } }
|
|
4
|
-
# Структура --data сформована з template/package.json.contains.json.
|
|
5
|
-
# FS-перевірки (`composer.json`, наявність `package.json` як такого) — у JS.
|
|
6
|
-
package php.package_json
|
|
7
|
-
|
|
8
|
-
import rego.v1
|
|
9
|
-
|
|
10
|
-
deny contains msg if {
|
|
11
|
-
some script_name, needles in data.template.contains.scripts
|
|
12
|
-
actual := object.get(object.get(input, "scripts", {}), script_name, "")
|
|
13
|
-
some needle in needles
|
|
14
|
-
not contains(actual, needle)
|
|
15
|
-
msg := sprintf("package.json: scripts.%s має містити %q (php.mdc)", [script_name, needle])
|
|
16
|
-
}
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
# Перевірка `package.json` (python.mdc).
|
|
2
|
-
#
|
|
3
|
-
# Канон надходить через --data: { "template": { "contains": ... } }
|
|
4
|
-
# Структура --data сформована з template/package.json.contains.json.
|
|
5
|
-
# FS-перевірки (наявність `package.json` як такого) — у JS.
|
|
6
|
-
package python.package_json
|
|
7
|
-
|
|
8
|
-
import rego.v1
|
|
9
|
-
|
|
10
|
-
deny contains msg if {
|
|
11
|
-
some script_name, needles in data.template.contains.scripts
|
|
12
|
-
actual := object.get(object.get(input, "scripts", {}), script_name, "")
|
|
13
|
-
some needle in needles
|
|
14
|
-
not contains(actual, needle)
|
|
15
|
-
msg := sprintf("package.json: scripts.%s має містити %q (python.mdc)", [script_name, needle])
|
|
16
|
-
}
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
# Перевірка `package.json` для rego (rego.mdc).
|
|
2
|
-
#
|
|
3
|
-
# Канон надходить через --data: { "template": { "snippet": ... } }
|
|
4
|
-
# Структура --data сформована з template/package.json.snippet.json.
|
|
5
|
-
# Дозволяємо whitespace навколо значення (trim_space) — допуск, який мав
|
|
6
|
-
# попередній inline-варіант.
|
|
7
|
-
package rego.package_json
|
|
8
|
-
|
|
9
|
-
import rego.v1
|
|
10
|
-
|
|
11
|
-
deny contains msg if {
|
|
12
|
-
some script_name, expected in data.template.snippet.scripts
|
|
13
|
-
actual := object.get(object.get(input, "scripts", {}), script_name, "")
|
|
14
|
-
trim_space(actual) != expected
|
|
15
|
-
msg := sprintf("package.json: scripts.%s має бути %q (rego.mdc)", [script_name, expected])
|
|
16
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{ "scripts": { "lint-rego": "n-cursor lint-rego" } }
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
# Перевірка `package.json` для правила rust (rust.mdc).
|
|
2
|
-
#
|
|
3
|
-
# Канон надходить через --data: { "template": { "contains": ... } }
|
|
4
|
-
# Структура --data сформована з template/package.json.contains.json.
|
|
5
|
-
# Перевіряємо substring-вимоги до scripts.lint-rust: усі три кроки
|
|
6
|
-
# (`cargo fmt`, `cargo clippy --fix`, фінальний `cargo clippy ... -D warnings`)
|
|
7
|
-
# мають бути присутніми у значенні скрипта.
|
|
8
|
-
package rust.package_json
|
|
9
|
-
|
|
10
|
-
import rego.v1
|
|
11
|
-
|
|
12
|
-
deny contains msg if {
|
|
13
|
-
some script_name, needles in data.template.contains.scripts
|
|
14
|
-
actual := object.get(object.get(input, "scripts", {}), script_name, "")
|
|
15
|
-
some needle in needles
|
|
16
|
-
not contains(actual, needle)
|
|
17
|
-
msg := sprintf("package.json: scripts.%s має містити %q (rust.mdc)", [script_name, needle])
|
|
18
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{ "scripts": { "lint": ["bun run lint-security"] } }
|