@nitra/cursor 1.13.15 → 1.13.26

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 (77) hide show
  1. package/.claude-template/hooks/normalize-decisions.sh +1 -1
  2. package/CHANGELOG.md +85 -0
  3. package/package.json +1 -1
  4. package/rules/abie/abie.mdc +1 -4
  5. package/rules/abie/policy/clean_merged_ignore_branches/clean_merged_ignore_branches.rego +21 -40
  6. package/rules/abie/policy/clean_merged_ignore_branches/template/clean-merged-branch.yml.snippet.yml +9 -0
  7. package/rules/adr/adr.mdc +2 -2
  8. package/rules/docker/docker.mdc +2 -50
  9. package/rules/docker/policy/lint_docker_yml/lint_docker_yml.rego +33 -47
  10. package/rules/docker/policy/lint_docker_yml/template/lint-docker.yml.snippet.yml +41 -0
  11. package/rules/docker/policy/package_json/package_json.rego +11 -28
  12. package/rules/docker/policy/package_json/template/package.json.snippet.json +1 -0
  13. package/rules/image-avif/policy/package_json/package_json.rego +21 -35
  14. package/rules/image-avif/policy/package_json/template/package.json.deny.json +5 -0
  15. package/rules/image-compress/image-compress.mdc +2 -8
  16. package/rules/image-compress/policy/package_json/package_json.rego +24 -65
  17. package/rules/image-compress/policy/package_json/template/package.json.contains.json +5 -0
  18. package/rules/image-compress/policy/package_json/template/package.json.deny.json +8 -0
  19. package/rules/js-bun-db/policy/package_json/package_json.rego +8 -21
  20. package/rules/js-bun-db/policy/package_json/template/package.json.deny.json +7 -0
  21. package/rules/js-bun-redis/policy/package_json/package_json.rego +8 -30
  22. package/rules/js-bun-redis/policy/package_json/template/package.json.deny.json +12 -0
  23. package/rules/js-lint/policy/jscpd/jscpd.rego +29 -23
  24. package/rules/js-lint/policy/jscpd/template/.jscpd.json.snippet.json +6 -0
  25. package/rules/js-lint/policy/lint_js_yml/lint_js_yml.rego +39 -47
  26. package/rules/js-lint/policy/lint_js_yml/template/lint-js.yml.snippet.yml +44 -0
  27. package/rules/js-lint/policy/package_json/package_json.rego +22 -42
  28. package/rules/js-lint/policy/package_json/template/package.json.snippet.json +6 -0
  29. package/rules/js-lint/policy/vscode_extensions/template/extensions.json.snippet.json +7 -0
  30. package/rules/js-lint/policy/vscode_extensions/vscode_extensions.rego +4 -17
  31. package/rules/js-run/policy/configmap/configmap.rego +11 -35
  32. package/rules/js-run/policy/configmap/template/configmap.yaml.contains.yml +4 -0
  33. package/rules/js-run/policy/jsconfig/jsconfig.rego +39 -46
  34. package/rules/js-run/policy/jsconfig/template/jsconfig.json.snippet.json +10 -0
  35. package/rules/js-run/policy/package_json/package_json.rego +10 -21
  36. package/rules/js-run/policy/package_json/template/package.json.deny.json +10 -0
  37. package/rules/php/php.mdc +2 -56
  38. package/rules/php/policy/lint_php_yml/lint_php_yml.rego +15 -13
  39. package/rules/php/policy/lint_php_yml/template/lint-php.yml.snippet.yml +47 -0
  40. package/rules/php/policy/package_json/package_json.rego +9 -12
  41. package/rules/php/policy/package_json/template/package.json.contains.json +5 -0
  42. package/rules/security/fix/trufflehog/check.mjs +45 -0
  43. package/rules/security/fix/trufflehog/template/.trufflehog-exclude.snippet.txt +6 -0
  44. package/rules/security/policy/lint_security_yml/lint_security_yml.rego +33 -0
  45. package/rules/security/policy/lint_security_yml/target.json +8 -0
  46. package/rules/security/policy/lint_security_yml/template/lint-security.yml.snippet.yml +31 -0
  47. package/rules/security/policy/package_json/template/package.json.deny.json +2 -2
  48. package/rules/security/policy/package_json/template/package.json.snippet.json +1 -1
  49. package/rules/security/security.mdc +17 -38
  50. package/rules/style-lint/policy/lint_style_yml/lint_style_yml.rego +14 -16
  51. package/rules/style-lint/policy/lint_style_yml/template/lint-style.yml.snippet.yml +39 -0
  52. package/rules/style-lint/policy/package_json/package_json.rego +22 -30
  53. package/rules/style-lint/policy/package_json/template/package.json.contains.json +5 -0
  54. package/rules/style-lint/policy/package_json/template/package.json.snippet.json +5 -0
  55. package/rules/style-lint/policy/vscode_extensions/template/extensions.json.snippet.json +1 -0
  56. package/rules/style-lint/policy/vscode_extensions/vscode_extensions.rego +5 -15
  57. package/rules/style-lint/policy/vscode_settings/template/settings.json.snippet.json +5 -0
  58. package/rules/style-lint/policy/vscode_settings/vscode_settings.rego +7 -16
  59. package/rules/text/policy/cspell/cspell.rego +39 -59
  60. package/rules/text/policy/cspell/template/.cspell.json.contains.json +3 -0
  61. package/rules/text/policy/cspell/template/.cspell.json.deny.json +5 -0
  62. package/rules/text/policy/cspell/template/.cspell.json.snippet.json +12 -0
  63. package/rules/text/policy/markdownlint/markdownlint.rego +37 -50
  64. package/rules/text/policy/markdownlint/template/.markdownlint-cli2.jsonc.snippet.jsonc +11 -0
  65. package/rules/text/policy/oxfmtrc/oxfmtrc.rego +23 -58
  66. package/rules/text/policy/oxfmtrc/template/.oxfmtrc.json.snippet.json +12 -0
  67. package/rules/text/policy/package_json/package_json.rego +14 -52
  68. package/rules/text/policy/package_json/template/package.json.deny.json +15 -0
  69. package/rules/text/policy/vscode_extensions/template/extensions.json.snippet.json +7 -0
  70. package/rules/text/policy/vscode_extensions/vscode_extensions.rego +4 -28
  71. package/rules/text/policy/vscode_settings/template/settings.json.snippet.json +9 -0
  72. package/rules/text/policy/vscode_settings/vscode_settings.rego +20 -42
  73. package/skills/adr-normalize/SKILL.md +2 -2
  74. package/rules/security/fix/gitleaks/check.mjs +0 -25
  75. package/rules/security/fix/gitleaks/template/.gitleaks.toml.snippet.toml +0 -12
  76. package/rules/security/policy/gitleaks/gitleaks.rego +0 -17
  77. package/rules/security/policy/gitleaks/target.json +0 -8
@@ -1,24 +1,15 @@
1
- # Порт перевірок `.oxfmtrc.json` з `npm/scripts/check-text.mjs` (text.mdc).
1
+ # Перевірка `.oxfmtrc.json` (text.mdc).
2
2
  #
3
- # Запуск (локально):
4
- # conftest test .oxfmtrc.json -p npm/policy/text --namespace text.oxfmtrc
3
+ # Канон надходить через --data: { "template": { "snippet": ... } }
4
+ # Структура --data сформована з template/.oxfmtrc.json.snippet.json.
5
+ # Generic walker: top-level scalar leaf-check + array subset-of (для ignorePatterns).
5
6
  #
6
- # Перевіряє: обовʼязкові ключі, канонічні значення (`semi=false`, `singleQuote=true`,
7
- # `tabWidth=2`, `useTabs=false`, `printWidth=120`), масив `ignorePatterns` з
8
- # канонічними glob-ами (hasura/metadata, schema.graphql, auto-imports.d.ts).
9
- #
10
- # FS-перевірки (наявність самого `.oxfmtrc.json`, `.prettierrc.*` файлів) живуть
11
- # у `check-text.mjs`. Тут — лише про вже завантажений input.
12
- #
13
- # Структура каталогу збігається зі шляхом пакету (regal: directory-package-mismatch).
14
- # Конвенція проєкту — `import rego.v1` + multi-value `deny contains msg if { … }`
15
- # (.cursor/rules/conftest.mdc). Лінт — `bun run lint-rego` (regal).
7
+ # Логіка, що ЛИШАЄТЬСЯ у rego (inverse — не виноситься у template):
8
+ # - required_keys: ключі, що мають бути присутні (presence-only, без точного значення).
16
9
  package text.oxfmtrc
17
10
 
18
11
  import rego.v1
19
12
 
20
- # ── Очікувані значення ─────────────────────────────────────────────────────
21
-
22
13
  required_keys := [
23
14
  "arrowParens",
24
15
  "printWidth",
@@ -31,60 +22,34 @@ required_keys := [
31
22
  "useTabs",
32
23
  ]
33
24
 
34
- required_ignore_patterns := {
35
- "**/hasura/metadata/**",
36
- "**/schema.graphql",
37
- "**/auto-imports.d.ts",
38
- }
39
-
40
- # ── deny: обовʼязкові ключі ────────────────────────────────────────────────
41
-
42
25
  deny contains msg if {
43
26
  some key in required_keys
44
27
  not key in object.keys(input)
45
28
  msg := sprintf(".oxfmtrc.json: відсутній обовʼязковий ключ %q (text.mdc)", [key])
46
29
  }
47
30
 
48
- # ── deny: канонічні значення ───────────────────────────────────────────────
49
- #
50
- # `object.get(…, sentinel)` робить значення визначеним — інакше при відсутньому
51
- # ключі порівняння дало б `undefined`, не `true`, і правило мовчки не спрацювало б.
52
-
53
- deny contains msg if {
54
- object.get(input, "semi", null) != false
55
- msg := ".oxfmtrc.json: semi має бути false (text.mdc)"
56
- }
57
-
58
31
  deny contains msg if {
59
- object.get(input, "singleQuote", null) != true
60
- msg := ".oxfmtrc.json: singleQuote має бути true (text.mdc)"
32
+ some key, expected_value in data.template.snippet
33
+ not is_array(expected_value)
34
+ not is_object(expected_value)
35
+ actual := object.get(input, key, null)
36
+ actual != expected_value
37
+ msg := sprintf(".oxfmtrc.json: %s має бути %v (text.mdc)", [key, expected_value])
61
38
  }
62
39
 
63
40
  deny contains msg if {
64
- object.get(input, "tabWidth", null) != 2
65
- msg := ".oxfmtrc.json: tabWidth має бути 2 (text.mdc)"
66
- }
67
-
68
- deny contains msg if {
69
- object.get(input, "useTabs", null) != false
70
- msg := ".oxfmtrc.json: useTabs має бути false (text.mdc)"
71
- }
72
-
73
- deny contains msg if {
74
- object.get(input, "printWidth", null) != 120
75
- msg := ".oxfmtrc.json: printWidth має бути 120 (text.mdc)"
76
- }
77
-
78
- # ── deny: ignorePatterns ───────────────────────────────────────────────────
79
-
80
- deny contains msg if {
81
- not is_array(object.get(input, "ignorePatterns", null))
82
- msg := ".oxfmtrc.json: додай масив ignorePatterns з канонічними glob-ами (text.mdc)"
41
+ some field, expected_values in data.template.snippet
42
+ is_array(expected_values)
43
+ not is_array(object.get(input, field, null))
44
+ msg := sprintf(".oxfmtrc.json: додай масив %s з канонічними glob-ами (text.mdc)", [field])
83
45
  }
84
46
 
85
47
  deny contains msg if {
86
- is_array(input.ignorePatterns)
87
- some pattern in required_ignore_patterns
88
- not pattern in {p | some p in input.ignorePatterns}
89
- msg := sprintf(".oxfmtrc.json ignorePatterns: додай %q (text.mdc)", [pattern])
48
+ some field, expected_values in data.template.snippet
49
+ is_array(expected_values)
50
+ is_array(object.get(input, field, null))
51
+ actual_set := {v | some v in input[field]}
52
+ some required in expected_values
53
+ not required in actual_set
54
+ msg := sprintf(".oxfmtrc.json %s: додай %q (text.mdc)", [field, required])
90
55
  }
@@ -0,0 +1,12 @@
1
+ {
2
+ "semi": false,
3
+ "singleQuote": true,
4
+ "tabWidth": 2,
5
+ "useTabs": false,
6
+ "printWidth": 120,
7
+ "ignorePatterns": [
8
+ "**/hasura/metadata/**",
9
+ "**/schema.graphql",
10
+ "**/auto-imports.d.ts"
11
+ ]
12
+ }
@@ -1,66 +1,34 @@
1
- # Порт текст-специфічних перевірок `package.json` з `npm/scripts/check-text.mjs` (text.mdc).
1
+ # Порт текст-специфічних перевірок `package.json` (text.mdc).
2
2
  #
3
- # Запуск (локально):
4
- # conftest test package.json -p npm/policy/text --namespace text.package_json
3
+ # Канон надходить через --data: { "template": { "deny": ... } }
4
+ # Структура --data сформована з template/package.json.deny.json:
5
+ # - `top-level`: top-level forbidden fields (e.g. `prettier`)
6
+ # - `dependencies` / `devDependencies`: forbidden packages.
5
7
  #
6
- # Перевіряє: відсутність Prettier (поле + конфіги в deps), `@nitra/cspell-dict ^2.0.0+`
7
- # у `devDependencies`, заборона `markdownlint-cli2` у dependencies/devDependencies.
8
- #
9
- # Перевірка скрипта `lint-text` (cspell, run-shellcheck-text.mjs, markdownlint, v8r,
10
- # обовʼязкові glob-и для v8r) — у JS-частині (`check-text.mjs`): занадто варіативна
11
- # для декларативної політики (3 режими v8r з різними вимогами до глобів).
12
- #
13
- # Структура каталогу збігається зі шляхом пакету (regal: directory-package-mismatch).
14
- # Конвенція проєкту — `import rego.v1` + multi-value `deny contains msg if { … }`
15
- # (.cursor/rules/conftest.mdc). Лінт — `bun run lint-rego` (regal).
8
+ # Логіка, що ЛИШАЄТЬСЯ у rego (inverse, не виноситься у template):
9
+ # - `@nitra/cspell-dict` ^2.0.0+ обовʼязковий у devDependencies (presence + semver range).
16
10
  package text.package_json
17
11
 
18
12
  import rego.v1
19
13
 
20
- # ── Заборонені пакети у dependencies/devDependencies ──────────────────────
21
-
22
- forbidden_packages := {
23
- "prettier": "Prettier заборонено — використовуй oxfmt (text.mdc)",
24
- "@nitra/prettier-config": "Prettier-конфіг заборонено — використовуй oxfmt (text.mdc)",
25
- }
26
-
27
- # ── deny: заборонене поле `prettier` у package.json ───────────────────────
28
-
29
14
  deny contains msg if {
30
- object.get(input, "prettier", null) != null
31
- msg := "package.json містить поле \"prettier\" — видали його (text.mdc)"
15
+ some field, reason in data.template.deny["top-level"]
16
+ object.get(input, field, null) != null
17
+ msg := sprintf("package.json містить поле %q — %s", [field, reason])
32
18
  }
33
19
 
34
- # ── deny: prettier у dependencies/devDependencies ─────────────────────────
35
-
36
20
  deny contains msg if {
37
- some pkg, hint in forbidden_packages
21
+ some pkg, reason in data.template.deny.dependencies
38
22
  pkg in object.keys(object.get(input, "dependencies", {}))
39
- msg := sprintf("package.json: dependencies містить %q — %s", [pkg, hint])
23
+ msg := sprintf("package.json: dependencies містить %q — %s", [pkg, reason])
40
24
  }
41
25
 
42
26
  deny contains msg if {
43
- some pkg, hint in forbidden_packages
27
+ some pkg, reason in data.template.deny.devDependencies
44
28
  pkg in object.keys(object.get(input, "devDependencies", {}))
45
- msg := sprintf("package.json: devDependencies містить %q — %s", [pkg, hint])
29
+ msg := sprintf("package.json: devDependencies містить %q — %s", [pkg, reason])
46
30
  }
47
31
 
48
- # ── deny: markdownlint-cli2 не повинен бути у залежностях ─────────────────
49
- #
50
- # Канонічний виклик — `bunx markdownlint-cli2` у `lint-text`, без оголошення пакета.
51
-
52
- deny contains msg if {
53
- "markdownlint-cli2" in object.keys(object.get(input, "dependencies", {}))
54
- msg := "package.json: dependencies містить markdownlint-cli2 — використовуй bunx у lint-text (text.mdc)"
55
- }
56
-
57
- deny contains msg if {
58
- "markdownlint-cli2" in object.keys(object.get(input, "devDependencies", {}))
59
- msg := "package.json: devDependencies містить markdownlint-cli2 — використовуй bunx у lint-text (text.mdc)"
60
- }
61
-
62
- # ── deny: @nitra/cspell-dict ^2.0.0+ обовʼязковий ─────────────────────────
63
-
64
32
  deny contains msg if {
65
33
  dev := object.get(input, "devDependencies", {})
66
34
  not "@nitra/cspell-dict" in object.keys(dev)
@@ -74,13 +42,7 @@ deny contains msg if {
74
42
  msg := sprintf("@nitra/cspell-dict має бути ^2.0.0 або новіший (зараз %q) (text.mdc)", [range])
75
43
  }
76
44
 
77
- # ── helpers ────────────────────────────────────────────────────────────────
78
-
79
- # Чи мажорна версія cspell-dict ≥ 2. Підтримує `^2.0.0`, `~2.x`, `2.5.0`,
80
- # `>=2.0.0`, `workspace:*` (тоді fallback false), із префіксом і без.
81
- # Regex `^[\^~>=<]*\s*(\d+)` дістає першу цифру після опціональних range-операторів.
82
45
  cspell_dict_major_at_least_2(range) if {
83
- # `regex.find_n` повертає масив збігів; беремо перший і дивимось на перше число.
84
46
  match := regex.find_n(`^[\^~>=<]*\s*(\d+)`, range, 1)
85
47
  count(match) > 0
86
48
  major := to_number(regex.replace(match[0], `^[\^~>=<]*\s*`, ""))
@@ -0,0 +1,15 @@
1
+ {
2
+ "top-level": {
3
+ "prettier": "Prettier заборонено — використовуй oxfmt (text.mdc)"
4
+ },
5
+ "dependencies": {
6
+ "prettier": "Prettier заборонено — використовуй oxfmt (text.mdc)",
7
+ "@nitra/prettier-config": "Prettier-конфіг заборонено — використовуй oxfmt (text.mdc)",
8
+ "markdownlint-cli2": "використовуй bunx у lint-text (text.mdc)"
9
+ },
10
+ "devDependencies": {
11
+ "prettier": "Prettier заборонено — використовуй oxfmt (text.mdc)",
12
+ "@nitra/prettier-config": "Prettier-конфіг заборонено — використовуй oxfmt (text.mdc)",
13
+ "markdownlint-cli2": "використовуй bunx у lint-text (text.mdc)"
14
+ }
15
+ }
@@ -0,0 +1,7 @@
1
+ {
2
+ "recommendations": [
3
+ "DavidAnson.vscode-markdownlint",
4
+ "oxc.oxc-vscode",
5
+ "timonwong.shellcheck"
6
+ ]
7
+ }
@@ -1,36 +1,12 @@
1
1
  # Перевірка `.vscode/extensions.json` для text (text.mdc).
2
2
  #
3
- # Запуск (локально):
4
- # conftest test .vscode/extensions.json -p npm/policy/text/vscode_extensions \
5
- # --namespace text.vscode_extensions
6
- #
7
- # Canonical (text.mdc): у `recommendations` мають бути три розширення
8
- # - DavidAnson.vscode-markdownlint
9
- # - oxc.oxc-vscode
10
- # - timonwong.shellcheck
11
- #
12
- # Канон задає мінімум — додаткові записи (від інших правил) дозволені.
13
- #
14
- # Структура каталогу збігається зі шляхом пакету (regal: directory-package-mismatch).
3
+ # Канон надходить через --data: { "template": { "snippet": ... } }
15
4
  package text.vscode_extensions
16
5
 
17
6
  import rego.v1
18
7
 
19
- required_extensions := {
20
- "DavidAnson.vscode-markdownlint",
21
- "oxc.oxc-vscode",
22
- "timonwong.shellcheck",
23
- }
24
-
25
- missing_extension_template := ".vscode/extensions.json: recommendations має містити %q (text.mdc)"
26
-
27
- # Множина усіх записів `recommendations` (вираз поза deny — щоб regal не лаявся
28
- # performance/non-loop-expression: інакше `object.get` виконувався б на кожній
29
- # ітерації по `required_extensions`).
30
- recommendations_set := {r | some r in object.get(input, "recommendations", [])}
31
-
32
8
  deny contains msg if {
33
- some required in required_extensions
34
- not required in recommendations_set
35
- msg := sprintf(missing_extension_template, [required])
9
+ some rec in data.template.snippet.recommendations
10
+ not rec in {r | some r in object.get(input, "recommendations", [])}
11
+ msg := sprintf(".vscode/extensions.json: recommendations має містити %q (text.mdc)", [rec])
36
12
  }
@@ -0,0 +1,9 @@
1
+ {
2
+ "editor.formatOnSave": true,
3
+ "[javascript]": { "editor.defaultFormatter": "oxc.oxc-vscode" },
4
+ "[typescript]": { "editor.defaultFormatter": "oxc.oxc-vscode" },
5
+ "[json]": { "editor.defaultFormatter": "oxc.oxc-vscode" },
6
+ "[vue]": { "editor.defaultFormatter": "oxc.oxc-vscode" },
7
+ "[css]": { "editor.defaultFormatter": "oxc.oxc-vscode" },
8
+ "[html]": { "editor.defaultFormatter": "oxc.oxc-vscode" }
9
+ }
@@ -1,56 +1,34 @@
1
1
  # Перевірка `.vscode/settings.json` для text (text.mdc).
2
2
  #
3
- # Запуск (локально):
4
- # conftest test .vscode/settings.json -p npm/policy/text/vscode_settings \
5
- # --namespace text.vscode_settings
6
- #
7
- # Canonical (text.mdc):
8
- # { "editor.formatOnSave": true,
9
- # "[javascript]": { "editor.defaultFormatter": "oxc.oxc-vscode" },
10
- # "[typescript]": { "editor.defaultFormatter": "oxc.oxc-vscode" },
11
- # "[json]": { "editor.defaultFormatter": "oxc.oxc-vscode" },
12
- # "[vue]": { "editor.defaultFormatter": "oxc.oxc-vscode" },
13
- # "[css]": { "editor.defaultFormatter": "oxc.oxc-vscode" },
14
- # "[html]": { "editor.defaultFormatter": "oxc.oxc-vscode" } }
15
- #
16
- # Структура каталогу збігається зі шляхом пакету (regal: directory-package-mismatch).
3
+ # Канон надходить через --data: { "template": { "snippet": ... } }
4
+ # Структура --data сформована з template/settings.json.snippet.json.
17
5
  package text.vscode_settings
18
6
 
19
7
  import rego.v1
20
8
 
21
- language_keys := {"[javascript]", "[typescript]", "[json]", "[vue]", "[css]", "[html]"}
22
-
23
- # Шаблони повідомлень — через `concat` для regal style/line-length.
24
- lang_block_not_object_template := concat(" ", [
25
- ".vscode/settings.json: %q має бути обʼєктом з",
26
- "\"editor.defaultFormatter\": \"oxc.oxc-vscode\" (text.mdc)",
27
- ])
28
-
29
- lang_wrong_formatter_template := concat(" ", [
30
- ".vscode/settings.json: %q має використовувати",
31
- "\"oxc.oxc-vscode\" як editor.defaultFormatter (text.mdc)",
32
- ])
33
-
34
- # ── deny: editor.formatOnSave ────────────────────────────────────────────
35
-
36
9
  deny contains msg if {
37
- object.get(input, "editor.formatOnSave", null) != true
38
- msg := ".vscode/settings.json: \"editor.formatOnSave\" має бути true (text.mdc)"
10
+ some key, expected_value in data.template.snippet
11
+ not is_object(expected_value)
12
+ actual := object.get(input, key, null)
13
+ actual != expected_value
14
+ msg := sprintf(".vscode/settings.json: \"%s\" має бути %v (text.mdc)", [key, expected_value])
39
15
  }
40
16
 
41
- # ── deny: [lang].editor.defaultFormatter ────────────────────────────────
42
-
43
17
  deny contains msg if {
44
- some key in language_keys
45
- block := object.get(input, key, {})
46
- not is_object(block)
47
- msg := sprintf(lang_block_not_object_template, [key])
18
+ some block_key, expected_inner in data.template.snippet
19
+ is_object(expected_inner)
20
+ inner := object.get(input, block_key, {})
21
+ is_object(inner)
22
+ some leaf_key, expected_value in expected_inner
23
+ actual := object.get(inner, leaf_key, null)
24
+ actual != expected_value
25
+ msg := sprintf(".vscode/settings.json: %s.%s має бути %v (text.mdc)", [block_key, leaf_key, expected_value])
48
26
  }
49
27
 
50
28
  deny contains msg if {
51
- some key in language_keys
52
- block := object.get(input, key, {})
53
- is_object(block)
54
- object.get(block, "editor.defaultFormatter", null) != "oxc.oxc-vscode"
55
- msg := sprintf(lang_wrong_formatter_template, [key])
29
+ some block_key, expected_inner in data.template.snippet
30
+ is_object(expected_inner)
31
+ raw := object.get(input, block_key, null)
32
+ not is_object(raw)
33
+ msg := sprintf(".vscode/settings.json: %s має бути обʼєктом (text.mdc)", [block_key])
56
34
  }
@@ -55,11 +55,11 @@ description: >-
55
55
  - Відкотити конкретний файл: `git checkout -- docs/adr/<file>` (для `rewrite` цього мало — треба ще `git restore --staged` і `rm` нового).
56
56
  - Відкотити весь батч: `git checkout -- docs/adr/ && git clean -f docs/adr/` (видалить і untracked rewrite-результати).
57
57
 
58
- 5. **Повторити для наступного батчу**, якщо чернеток ще багато. Кожен запуск обробляє до `ADR_NORMALIZE_BATCH` файлів (default 30, найстарші за часовою позначкою у назві).
58
+ 5. **Повторити для наступного батчу**, якщо чернеток ще багато. Кожен запуск обробляє до `ADR_NORMALIZE_BATCH` файлів (default 10, найстарші за часовою позначкою у назві).
59
59
 
60
60
  ## Tuning через ENV
61
61
 
62
- - `ADR_NORMALIZE_BATCH=10` — менший батч (менше токенів, частіші коміти).
62
+ - `ADR_NORMALIZE_BATCH=30` — більший батч (менше викликів LLM, більше токенів за раз).
63
63
  - `ADR_NORMALIZE_MODEL=opus` — інша модель `claude -p`.
64
64
  - `ADR_NORMALIZE_CURSOR_MODEL=…` — інша модель для cursor-agent fallback.
65
65
 
@@ -1,25 +0,0 @@
1
- /**
2
- * FS-частина правила `security`.
3
- *
4
- * Перевіряє:
5
- * - наявність `package.json` (структуру валідує Rego);
6
- * - контекстне pass-повідомлення для JS-концерну.
7
- *
8
- * Наявність і вміст `.gitleaks.toml` (`[extend].useDefault = true`) тепер
9
- * перевіряє policy `security.gitleaks`.
10
- */
11
- import { existsSync } from 'node:fs'
12
-
13
- import { createCheckReporter } from '../../../../scripts/utils/check-reporter.mjs'
14
-
15
- export async function check() {
16
- const reporter = createCheckReporter()
17
- const { pass, fail } = reporter
18
- if (!existsSync('package.json')) {
19
- fail('package.json не знайдено в корені — додай (security.mdc)')
20
- return reporter.getExitCode()
21
- }
22
- pass('package.json є (структуру перевіряє Rego)')
23
- pass('.gitleaks.toml перевіряє npx @nitra/cursor check → security.gitleaks')
24
- return reporter.getExitCode()
25
- }
@@ -1,12 +0,0 @@
1
- [extend]
2
- useDefault = true
3
-
4
- [allowlist]
5
- paths = [
6
- '''(^|/)node_modules(/|$)''',
7
- '''(^|/)\.git(/|$)''',
8
- '''(^|/)dist(/|$)''',
9
- '''(^|/)build(/|$)''',
10
- '''.*\.lock$''',
11
- '''.*fixtures?/.*'''
12
- ]
@@ -1,17 +0,0 @@
1
- # Перевірка `.gitleaks.toml` для security (security.mdc).
2
- #
3
- # Канонічна мінімальна вимога: `[extend].useDefault = true`, щоб локальний
4
- # конфіг не вимикав стандартні правила gitleaks. Додаткові локальні правила
5
- # дозволені.
6
- #
7
- # Структура каталогу збігається зі шляхом пакету (regal: directory-package-mismatch).
8
- # Конвенція проєкту — `import rego.v1` + multi-value `deny contains msg if { … }`
9
- # (.cursor/rules/conftest.mdc). Лінт — `bun run lint-rego` (regal).
10
- package security.gitleaks
11
-
12
- import rego.v1
13
-
14
- deny contains msg if {
15
- object.get(object.get(input, "extend", {}), "useDefault", null) != true
16
- msg := ".gitleaks.toml: [extend].useDefault має бути true (security.mdc)"
17
- }
@@ -1,8 +0,0 @@
1
- {
2
- "$schema": "https://unpkg.com/@nitra/cursor/schemas/target.json",
3
- "files": {
4
- "single": ".gitleaks.toml",
5
- "required": true
6
- },
7
- "missingMessage": ".gitleaks.toml не знайдено — створи за каноном security.mdc"
8
- }