@nitra/cursor 5.3.4 → 5.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.
Files changed (151) hide show
  1. package/.claude-template/settings.template.json +2 -2
  2. package/.pi-template/extensions/n-cursor-adr/docs/index.md +13 -24
  3. package/CHANGELOG.md +11 -0
  4. package/bin/n-cursor.js +43 -22
  5. package/lib/docs/models.md +29 -18
  6. package/lib/docs/omlx-trace.md +51 -0
  7. package/lib/docs/omlx.md +31 -15
  8. package/lib/omlx.mjs +2 -5
  9. package/package.json +1 -1
  10. package/rules/abie/docs/fix.md +17 -11
  11. package/rules/adr/docs/fix.md +25 -140
  12. package/rules/bun/docs/fix.md +18 -151
  13. package/rules/capacitor/docs/fix.md +16 -13
  14. package/rules/capacitor/js/docs/platforms.md +31 -43
  15. package/rules/changelog/docs/fix.md +25 -169
  16. package/rules/ci4/docs/fix.md +11 -14
  17. package/rules/doc-files/doc-files.mdc +60 -0
  18. package/rules/doc-files/docs/fix.md +31 -0
  19. package/rules/doc-files/fix.mjs +19 -0
  20. package/{skills → rules}/doc-files/js/docgen-extract.mjs +42 -19
  21. package/{skills → rules}/doc-files/js/docgen-ignore.mjs +2 -1
  22. package/{skills → rules}/doc-files/js/docgen-scan.mjs +9 -1
  23. package/{skills → rules}/doc-files/js/docs/docgen-crc.md +1 -1
  24. package/{skills → rules}/doc-files/js/docs/docgen-extract-anchors.md +1 -1
  25. package/{skills → rules}/doc-files/js/docs/docgen-extract.md +2 -2
  26. package/{skills → rules}/doc-files/js/docs/docgen-files-batch.md +1 -1
  27. package/{skills → rules}/doc-files/js/docs/docgen-gen.md +1 -1
  28. package/{skills → rules}/doc-files/js/docs/docgen-ignore.md +4 -4
  29. package/rules/doc-files/js/docs/docgen-prompts.md +39 -0
  30. package/rules/doc-files/js/docs/docgen-scan.md +54 -0
  31. package/rules/doc-files/js/docs/lint.md +36 -0
  32. package/rules/doc-files/js/docs/units-js.md +31 -0
  33. package/rules/doc-files/js/docs/units-rs.md +35 -0
  34. package/rules/doc-files/js/docs/units.md +30 -0
  35. package/rules/doc-files/js/lint.mjs +96 -0
  36. package/{skills → rules}/doc-files/js/units-rs.mjs +37 -17
  37. package/rules/doc-files/lint/docs/lint.md +37 -0
  38. package/rules/doc-files/lint/lint.mjs +105 -0
  39. package/rules/doc-files/meta.json +1 -0
  40. package/rules/docker/docs/fix.md +21 -161
  41. package/rules/efes/docs/fix.md +23 -194
  42. package/rules/feedback/docs/fix.md +10 -8
  43. package/rules/ga/docs/fix.md +10 -5
  44. package/rules/graphql/docs/fix.md +23 -119
  45. package/rules/hasura/docs/fix.md +19 -5
  46. package/rules/hasura/js/docs/internal_urls.md +34 -307
  47. package/rules/image-avif/docs/fix.md +16 -127
  48. package/rules/image-compress/docs/fix.md +20 -141
  49. package/rules/image-compress/js/docs/package_setup.md +22 -182
  50. package/rules/js-bun-db/docs/fix.md +23 -139
  51. package/rules/js-bun-db/js/docs/safety.md +33 -221
  52. package/rules/js-bun-redis/docs/fix.md +25 -114
  53. package/rules/js-bun-redis/js/docs/imports.md +18 -166
  54. package/rules/js-lint/docs/fix.md +30 -108
  55. package/rules/js-lint/js/docs/lint-findings.md +37 -17
  56. package/rules/js-lint/js/docs/lint.md +22 -238
  57. package/rules/js-lint/js/docs/tooling.md +34 -331
  58. package/rules/js-lint-ci/docs/fix.md +16 -149
  59. package/rules/js-lint-ci/js/docs/lint.md +16 -136
  60. package/rules/js-mssql/docs/fix.md +18 -123
  61. package/rules/js-mssql/js/docs/deps.md +28 -251
  62. package/rules/js-run/docs/fix.md +23 -138
  63. package/rules/js-run/js/docs/runtime.md +24 -378
  64. package/rules/k8s/docs/fix.md +18 -123
  65. package/rules/nginx-default-tpl/docs/fix.md +22 -118
  66. package/rules/nginx-default-tpl/js/docs/template.md +38 -360
  67. package/rules/npm-module/docs/fix.md +27 -89
  68. package/rules/npm-module/js/docs/header_doc_pointer.md +15 -15
  69. package/rules/npm-module/js/docs/package_structure.md +36 -258
  70. package/rules/npm-module/js/docs/rule_meta.md +25 -127
  71. package/rules/npm-module/js/docs/skill_meta.md +18 -180
  72. package/rules/php/docs/fix.md +21 -98
  73. package/rules/php/js/docs/tooling.md +20 -143
  74. package/rules/python/docs/fix.md +25 -157
  75. package/rules/python/js/docs/applies.md +20 -98
  76. package/rules/python/js/docs/tooling.md +27 -144
  77. package/rules/rego/docs/fix.md +24 -112
  78. package/rules/rego/js/docs/applies.md +20 -164
  79. package/rules/rego/js/docs/lint.md +15 -110
  80. package/rules/release/docs/fix.md +16 -114
  81. package/rules/rust/docs/fix.md +24 -119
  82. package/rules/rust/js/docs/applies.md +20 -129
  83. package/rules/security/docs/fix.md +21 -78
  84. package/rules/security/js/docs/sample_secret.md +23 -182
  85. package/rules/security/js/docs/trufflehog.md +19 -128
  86. package/rules/style-lint/docs/fix.md +16 -150
  87. package/rules/style-lint/js/docs/lint.md +21 -172
  88. package/rules/style-lint/js/docs/tooling.md +19 -184
  89. package/rules/tauri/docs/fix.md +26 -152
  90. package/rules/tauri/js/docs/cargo_mutants_config.md +21 -159
  91. package/rules/tauri/js/docs/tooling.md +20 -217
  92. package/rules/test/docs/fix.md +19 -127
  93. package/rules/test/js/data/stryker_config/docs/stryker.config.baseline.md +15 -127
  94. package/rules/test/js/data/stryker_config/docs/stryker.config.vue.baseline.md +17 -153
  95. package/rules/test/js/docs/cargo_mutants_config.md +24 -164
  96. package/rules/test/js/docs/location.md +24 -126
  97. package/rules/test/js/docs/no-process-chdir.md +20 -151
  98. package/rules/test/js/docs/no-relative-fs-path.md +24 -261
  99. package/rules/test/js/docs/stryker_config.md +48 -148
  100. package/rules/test/js/docs/vitest-config-pool-forks.md +21 -164
  101. package/rules/text/docs/fix.md +25 -113
  102. package/rules/text/js/docs/forbidden-prettier.md +21 -132
  103. package/rules/text/js/docs/formatting.md +60 -251
  104. package/rules/text/js/docs/lint.md +17 -114
  105. package/rules/vue/docs/fix.md +25 -118
  106. package/rules/vue/js/docs/packages.md +25 -323
  107. package/rules/worktree/docs/fix.md +31 -150
  108. package/scripts/coverage-classify/docs/index.md +23 -209
  109. package/scripts/coverage-classify/docs/verdict-schema.md +14 -159
  110. package/scripts/dispatcher/docs/trace.md +35 -0
  111. package/scripts/docs/auto-rules.md +37 -361
  112. package/scripts/docs/lint-cli.md +12 -13
  113. package/scripts/docs/post-tool-use-fix.md +16 -15
  114. package/scripts/docs/skills-cli.md +26 -23
  115. package/scripts/docs/sync-claude-config.md +94 -34
  116. package/scripts/docs/worktree-cli.md +11 -34
  117. package/scripts/lib/docs/assert-project-root.md +14 -16
  118. package/scripts/lib/docs/changed-files.md +24 -139
  119. package/scripts/lib/docs/discover-check-rules-from-cursor.md +14 -146
  120. package/scripts/lib/docs/rule-predicates.md +20 -17
  121. package/scripts/lib/docs/run-rule-cli.md +14 -18
  122. package/scripts/lib/docs/run-rule.md +13 -20
  123. package/scripts/lib/docs/run-standard-rule.md +12 -15
  124. package/scripts/lib/docs/sync-gitignore-worktree.md +15 -18
  125. package/scripts/lib/rule-predicates.mjs +1 -1
  126. package/scripts/sync-claude-config.mjs +4 -1
  127. package/scripts/utils/docs/with-lock.md +19 -12
  128. package/scripts/utils/with-lock.mjs +4 -2
  129. package/skills/doc-aggregate/SKILL.md +2 -2
  130. package/skills/doc-aggregate/js/docgen-ignore.mjs +6 -6
  131. package/skills/doc-aggregate/js/docs/docgen-ignore.md +1 -1
  132. package/skills/doc-aggregate/js/docs/docgen-scan.md +78 -0
  133. package/skills/doc-files/.changes/260612-0031.md +5 -0
  134. package/skills/doc-files/.changes/260612-0036.md +5 -0
  135. package/skills/doc-files/.changes/260612-0114.md +5 -0
  136. package/skills/doc-files/SKILL.md +6 -6
  137. package/skills/fix/js/docs/llm-worker.md +17 -15
  138. package/skills/fix/js/docs/orchestrator.md +30 -23
  139. package/skills/fix/js/docs/t0.md +26 -16
  140. package/skills/start-check/js/docs/check.md +26 -22
  141. package/skills/taze/js/docs/diff.md +44 -20
  142. package/skills/doc-files/js/docs/docgen-prompts.md +0 -32
  143. package/skills/doc-files/js/docs/docgen-scan.md +0 -25
  144. package/skills/doc-files/js/docs/units-rs.md +0 -35
  145. /package/{skills → rules}/doc-files/js/docgen-crc.mjs +0 -0
  146. /package/{skills → rules}/doc-files/js/docgen-extract-anchors.mjs +0 -0
  147. /package/{skills → rules}/doc-files/js/docgen-files-batch.mjs +0 -0
  148. /package/{skills → rules}/doc-files/js/docgen-gen.mjs +0 -0
  149. /package/{skills → rules}/doc-files/js/docgen-prompts.mjs +0 -0
  150. /package/{skills → rules}/doc-files/js/units-js.mjs +0 -0
  151. /package/{skills → rules}/doc-files/js/units.mjs +0 -0
@@ -1,137 +1,35 @@
1
+ ---
2
+ docgen:
3
+ source: npm/rules/npm-module/js/rule_meta.mjs
4
+ crc: fa29bd00
5
+ score: 100
6
+ ---
7
+
1
8
  # rule_meta.mjs
2
9
 
3
10
  ## Огляд
4
11
 
5
- Модуль `rule_meta.mjs` реалізує перевірку метаданих правил пакета `@nitra/cursor`. Він є частиною концерну правила `npm-module` й обслуговує валідацію файлів `npm/rules/<id>/meta.json` у репозиторії пакета.
6
-
7
- Логіка перевірки покриває такі інваріанти для кожного підкаталогу `npm/rules/<id>/`:
8
-
9
- - наявність валідного `meta.json`;
10
- - коректність поля `auto`, якщо воно присутнє (розпізнаваність специфікації через `parseRuleAutoSpec`: значення `"завжди"`, масив, `{glob}` або `{predicate}`);
11
- - для специфікації `{predicate}` — наявність відповідного імені у реєстрі `RULE_PREDICATES`;
12
- - коректність поля `lint`, якщо воно присутнє (`"quick"` чи `"ci"`), з обовʼязковою наявністю файлу `js/lint.mjs` у каталозі правила;
13
- - відсутність застарілого `auto.md` поряд із `meta.json` (міграція метаданих у `meta.json` вже завершена).
14
-
15
- Перевірка застосовна виключно у репо самого пакета `@nitra/cursor`, де існує каталог `npm/rules/`. У споживацьких репо такого каталогу немає, тож модуль м’яко рапортує `pass` і завершується кодом виходу `0`.
16
-
17
- Модуль експортує єдину функцію `check`, яка повертає `Promise<number>` із POSIX-кодом виходу: `0` — порушень немає, `1` — є хоча б одне порушення. Звітування реалізоване через інстанс репортера, отриманий від `createCheckReporter`.
18
-
19
- ## Експорти / API
20
-
21
- | Експорт | Тип | Призначення |
22
- | -------------------------------------- | ---------------------------- | ---------------------------------------------------------------------------------------------------------- |
23
- | `check(cwd?: string): Promise<number>` | іменований експорт (функція) | Валідує всі `npm/rules/<id>/meta.json` у переданому корені репозиторію та повертає підсумковий код виходу. |
24
-
25
- Інших експортів (default, типи, константи) модуль не має.
26
-
27
- ## Функції
28
-
29
- ### `check(cwd = process.cwd())`
30
-
31
- Валідує всі `meta.json` у `<cwd>/npm/rules/<id>/`.
32
-
33
- - **Сигнатура:** `export function check(cwd?: string): Promise<number>`
34
- - **Параметри:**
35
- - `cwd` — рядок із абсолютним або відносним шляхом до кореня репозиторію. Необовʼязковий. Якщо не вказано, використовується `process.cwd()` (поточний робочий каталог процесу Node).
36
- - **Повертає:** `Promise<number>`, що резолвиться у код виходу від репортера (`reporter.getExitCode()`). Конвенція:
37
- - `0` — усі знайдені правила пройшли валідацію, або каталог `npm/rules/` відсутній (у такому випадку додатково логиться `pass`-повідомлення `"npm/rules/ відсутній — немає правил для валідації"`);
38
- - `1` — зафіксовано принаймні одне порушення (зокрема: залишковий `auto.md`, відсутній/невалідний `meta.json`, нерозпізнаний `auto`, невідомий `predicate`, нерозпізнаний `lint`, або `lint` без `js/lint.mjs`).
39
- - **Side effects:**
40
- - Виконує синхронне читання файлової системи: `existsSync` для перевірки наявності `npm/rules/`, `npm/rules/<id>/auto.md`, `npm/rules/<id>/js/lint.mjs`; `readdirSync` зі списком підкаталогів `npm/rules/`.
41
- - Делегує читання та парсинг `meta.json` у `readRuleMetaRaw` (також синхронне читання файла).
42
- - Викликає методи репортера (`reporter.pass`, `reporter.fail`), які за домовленістю виводять статусні повідомлення (зазвичай у stdout/stderr — залежно від реалізації `createCheckReporter`).
43
- - Не змінює файли на диску, не запускає дочірніх процесів, не звертається до мережі.
44
- - **Алгоритм:**
45
- 1. Створює репортер: `reporter = createCheckReporter()`.
46
- 2. Обчислює `rulesDir = join(cwd, 'npm', 'rules')`.
47
- 3. Якщо `rulesDir` не існує — рапортує `pass` і резолвить `Promise.resolve(reporter.getExitCode())` (зазвичай `0`).
48
- 4. Інакше перебирає вміст `rulesDir` через `readdirSync(rulesDir, { withFileTypes: true })` і для кожного запису:
49
- - пропускає, якщо це не каталог (`!entry.isDirectory()`) або імʼя починається з крапки (`entry.name.startsWith('.')`);
50
- - встановлює локальний прапор `ruleOk = true`;
51
- - якщо знайдено залишковий `auto.md` у каталозі правила — `reporter.fail(...)`, `ruleOk = false`;
52
- - читає сирий обʼєкт метаданих через `readRuleMetaRaw(ruleDir)`. Якщо повернуто falsy — `reporter.fail("rules/<id>: відсутній або невалідний meta.json")` і `continue` (наступне правило);
53
- - якщо `raw.auto !== undefined` — парсить через `parseRuleAutoSpec(raw.auto)`:
54
- - якщо повернуто `null` — `reporter.fail(...)`, `ruleOk = false`;
55
- - інакше якщо в `spec` є ключ `'predicate'` і його значення немає у `RULE_PREDICATES` — `reporter.fail(...)`, `ruleOk = false`;
56
- - якщо `raw.lint !== undefined` — валідує через `parseRuleLintPhase(raw.lint)`:
57
- - якщо повернуто `null` — `reporter.fail(...)`, `ruleOk = false`;
58
- - інакше якщо немає файла `<ruleDir>/js/lint.mjs` — `reporter.fail(...)`, `ruleOk = false`;
59
- - наприкінці ітерації, якщо `ruleOk` усе ще `true` — `reporter.pass("rules/<id>: meta.json валідний")`.
60
- 5. Резолвить `Promise.resolve(reporter.getExitCode())` із підсумковим кодом виходу.
61
- - **Особливості реалізації:**
62
- - Усі гілки порушень для одного правила фіксуються незалежно одна від одної (наприклад, у тому ж проході може бути зафіксовано і нерозпізнаний `auto`, і нерозпізнаний `lint`). Виняток — повністю відсутній/невалідний `meta.json`: тоді решта перевірок для цього правила пропускається через `continue`.
63
- - Функція синхронно виконує всю роботу, але повертає `Promise<number>` через `Promise.resolve(...)` — для уніфікованої сигнатури з іншими `check`-модулями.
64
- - Перевірка `'predicate' in spec` дозволяє валідувати лише гілку `{predicate}`-специфікації; інші форми (`"завжди"`, масив, `{glob}`) уже визнані валідними самим `parseRuleAutoSpec`.
65
-
66
- ## Залежності
67
-
68
- ### Зовнішні (Node.js standard library)
69
-
70
- - `node:fs` — `existsSync` (перевірка існування файлів і каталогів), `readdirSync` (читання вмісту каталогу `npm/rules/`).
71
- - `node:path` — `join` (формування шляхів до каталогів і файлів).
72
-
73
- ### Внутрішні (репо-локальні)
74
-
75
- - `../../../scripts/lib/check-reporter.mjs` — `createCheckReporter()`. Створює репортер з методами `pass(msg)`, `fail(msg)`, `getExitCode()`; останній використовується для отримання підсумкового коду виходу.
76
- - `../../../scripts/lib/rule-meta.mjs`:
77
- - `readRuleMetaRaw(ruleDir)` — читає та парсить сирий `meta.json` із каталогу правила; повертає обʼєкт або falsy (за відсутності/невалідності файла).
78
- - `parseRuleAutoSpec(value)` — парсить значення поля `auto`; повертає валідовану специфікацію або `null` за нерозпізнаним вводом.
79
- - `parseRuleLintPhase(value)` — парсить значення поля `lint`; повертає валідовану фазу (`"quick"`/`"ci"`) або `null`.
80
- - `../../../scripts/lib/rule-predicates.mjs` — `RULE_PREDICATES`: обʼєкт-реєстр відомих імен предикатів; ключі використовуються для перевірки наявності предиката через `Object.hasOwn`.
81
-
82
- ### Глобальні
83
-
84
- - `process.cwd()` — використовується як дефолтний `cwd`.
85
-
86
- ## Потік виконання / Використання
87
-
88
- Модуль є check-функцією конкретного правила і підпорядкований конвенції `check-{id}` (тут — `rule_meta`). Очікуваний сценарій використання:
89
-
90
- 1. Виклик з вищерівневого скрипта (наприклад, агрегованої перевірки правил пакета):
91
-
92
- ```js
93
- import { check } from './npm/rules/npm-module/js/rule_meta.mjs'
94
-
95
- const exit = await check(process.cwd())
96
- process.exit(exit)
97
- ```
98
-
99
- У такому сценарії функцію викликають із кореня репозиторію пакета `@nitra/cursor`.
100
-
101
- 2. Запуск у репо-споживачі (де `npm/rules/` відсутній) — функція тихо рапортує `pass` і повертає `0`, не блокуючи pipeline.
102
- 3. Сценарій порушення: будь-який із описаних інваріантів спричиняє `fail`-звіт і код виходу `1`, що сигналізує CI зупинку.
12
+ Перевіряє наявність директорії npm/rules у вказаному шляху. Ітерує по всіх директоріях у директорії npm/rules. Для кожної директорії виконує перевірку наявності файлу auto.md та валідність полів auto та lint у конфігурації meta.json. Перевіряє наявність файлу js/lint.mjs у каталозі правила. Збирає результати валідації та повертає код виходу репортера.
103
13
 
104
- Типові точки інтеграції:
14
+ ## Поведінка
105
15
 
106
- - CI lint-фаза пакета `@nitra/cursor` (виклик в одному з кореневих скриптів `bun run lint` / спеціалізованої перевірки правил).
107
- - Локальний запуск через CLI з кореня репозиторію.
16
+ 1. Перевірка наявності директорії npm/rules у вказаному шляху.
17
+ 2. Ітерація по всіх директоріях у директорії npm/rules.
18
+ 3. Для кожної директорії виконується перевірка правила.
19
+ 4. Перевірка наявності файлу auto.md у директорії правила.
20
+ 5. Перевірка валідності поля auto у meta.json правила.
21
+ 6. Перевірка наявності поля lint у meta.json правила.
22
+ 7. Перевірка валідності поля lint у meta.json правила.
23
+ 8. Перевірка наявності файлу js/lint.mjs у каталозі правила.
24
+ 9. Збір результатів валідації.
25
+ 10. Повернення коду виходу репортера.
108
26
 
109
- Файл не має побічних ефектів під час імпорту: експортована функція не виконується самовільно — її викликає консьюмер.
27
+ ## Публічний API
110
28
 
111
- ## Rebuild Test
29
+ check Валідує всі `npm/rules/<id>/meta.json`.
112
30
 
113
- Контрольні питання, чиї відповіді достатні, щоб реконструювати модуль без перегляду коду:
31
+ ## Гарантії поведінки
114
32
 
115
- 1. Який каталог сканує функція `check`?
116
- - `<cwd>/npm/rules/`, де `cwd` необовʼязковий параметр (дефолт `process.cwd()`).
117
- 2. Як обробляється відсутність цього каталогу?
118
- - Рапортується `pass("npm/rules/ відсутній — немає правил для валідації")`, повертається `0`.
119
- 3. Які записи в `npm/rules/` пропускаються?
120
- - Не-каталоги та елементи, чиє імʼя починається з `.`.
121
- 4. За наявності якого файла поряд із `meta.json` фіксується порушення?
122
- - `auto.md` (повідомлення `"rules/<id>: залишковий auto.md — видали (метадані тепер у meta.json)"`).
123
- 5. Що відбувається, якщо `meta.json` відсутній або невалідний?
124
- - `reporter.fail("rules/<id>: відсутній або невалідний meta.json")` і `continue` до наступного правила.
125
- 6. Які гілки валідації поля `auto`?
126
- - Якщо `parseRuleAutoSpec` повертає `null` — fail (нерозпізнане).
127
- - Якщо специфікація містить ключ `predicate`, але його значення відсутнє в `RULE_PREDICATES` — fail (`невідомий predicate`).
128
- 7. Які гілки валідації поля `lint`?
129
- - Якщо `parseRuleLintPhase` повертає `null` — fail (`нерозпізнане, очікується "quick"|"ci"`).
130
- - Якщо валідне, але немає `js/lint.mjs` — fail (`lint:"..." але немає js/lint.mjs`).
131
- 8. Як формується підсумковий код виходу?
132
- - Через `reporter.getExitCode()`, обгорнутий у `Promise.resolve(...)`.
133
- 9. Чи синхронна реалізація?
134
- - Так: усі IO операції — синхронні (`existsSync`, `readdirSync`, `readRuleMetaRaw`); проміс використано лише для уніфікації сигнатури.
135
- 10. Які `pass`-повідомлення можливі?
136
- - `"npm/rules/ відсутній — немає правил для валідації"` (за відсутності каталогу).
137
- - `"rules/<id>: meta.json валідний"` (за успішної валідації окремого правила).
33
+ - Read-only: файл не виконує операцій запису у файлову систему.
34
+ - За невдачі повертає значення помилки (`false`/`null`/`Err`) замість генерування винятку чи паніки.
35
+ - Не звертається до мережі.
@@ -1,190 +1,28 @@
1
+ ---
2
+ docgen:
3
+ source: npm/rules/npm-module/js/skill_meta.mjs
4
+ crc: a069397b
5
+ score: 100
6
+ ---
7
+
1
8
  # skill_meta.mjs
2
9
 
3
10
  ## Огляд
4
11
 
5
- Модуль `skill_meta.mjs` перевірка валідності метаданих скілів (`meta.json`) пакета `@nitra/cursor`. Належить до концерну правила `npm-module` (тека `npm/rules/npm-module/js/`).
6
-
7
- Перевірка застосовується **виключно в репозиторії пакета**, де є каталог `npm/skills/`. Якщо каталог відсутній (наприклад, у проєктах-споживачах залежності), перевірка пропускається без помилки (повертає `pass`).
8
-
9
- Для кожного підкаталогу `npm/skills/<id>/` модуль виконує контракт:
10
-
11
- - забороняється залишковий файл `auto.md` (метадані мігровані на `meta.json`);
12
- - файл `meta.json` має бути присутнім і валідним JSON-об'єктом з очікуваною структурою;
13
- - поле `worktree` обов'язкове і має бути `boolean`;
14
- - поле `auto` опціональне, але якщо є — має бути або рядком `"завжди"`, або непорожнім масивом рядків.
15
-
16
- Результат акумулюється через `check-reporter` і повертається кодом виходу `0` (OK) або `1` (порушення).
17
-
18
- ## Експорти / API
19
-
20
- | Експорт | Тип | Призначення |
21
- | ------- | ---------- | -------------------------------------------------------------------------- |
22
- | `check` | `function` | Іменований експорт; функція-перевірка метаданих скілів у вказаному корені. |
23
-
24
- Модуль є ESM (`.mjs`), без `default` експорту.
25
-
26
- ## Функції
27
-
28
- ### `check(cwd?)`
29
-
30
- **Сигнатура:**
31
-
32
- ```js
33
- export function check(cwd = process.cwd()): Promise<number>
34
- ```
35
-
36
- **Параметри:**
37
-
38
- | Параметр | Тип | Обов'язковий | За замовчуванням | Опис |
39
- | -------- | -------- | ------------ | ---------------- | ---------------------------------------------------------------- |
40
- | `cwd` | `string` | ні | `process.cwd()` | Корінь репозиторію; від нього резолвиться шлях до `npm/skills/`. |
41
-
42
- **Повертає:**
43
-
44
- `Promise<number>` — код виходу від `reporter.getExitCode()`:
45
-
46
- - `0` — усі перевірені скіли валідні (або каталог `npm/skills/` відсутній);
47
- - `1` — щонайменше одне порушення зафіксовано через `reporter.fail(...)`.
48
-
49
- Хоча всередині немає `async`/`await`, функція обертає результат у `Promise.resolve(...)` для однорідного API з іншими `check`-функціями в цьому проєкті.
50
-
51
- **Алгоритм:**
52
-
53
- 1. Створюється локальний звітник: `reporter = createCheckReporter()`.
54
- 2. Будується шлях `skillsDir = join(cwd, 'npm', 'skills')`.
55
- 3. Якщо `skillsDir` не існує (`existsSync(...) === false`):
56
- - викликається `reporter.pass('npm/skills/ відсутній — немає скілів для валідації')`;
57
- - повертається `Promise.resolve(reporter.getExitCode())` (рання гілка).
58
- 4. Інакше — ітерація `readdirSync(skillsDir, { withFileTypes: true })`:
59
- - пропускаються не-директорії та назви, що починаються з крапки (`.` префікс);
60
- - для кожного скіла `id = entry.name` будується `skillDir = join(skillsDir, id)` і прапор `skillOk = true`.
61
- 5. Для кожного скіла послідовно перевіряється:
62
- - **Залишковий `auto.md`**: якщо `existsSync(join(skillDir, 'auto.md'))`, фіксується
63
- `fail("skills/<id>: залишковий auto.md — видали (метадані тепер у meta.json)")` і `skillOk = false`.
64
- - **`meta.json` присутній/валідний**: викликається `raw = readSkillMetaRaw(skillDir)`.
65
- Якщо `raw` falsy — фіксується `fail("skills/<id>: відсутній або невалідний meta.json ...")` і виконується `continue` (решта перевірок для цього скіла пропускається).
66
- - **Тип `worktree`**: якщо `typeof raw.worktree !== 'boolean'` — `fail("skills/<id>: meta.json.worktree має бути boolean")` і `skillOk = false`.
67
- - **Розпізнаваність `auto`**: якщо `raw.auto !== undefined` і `parseSkillAutoSpec(raw.auto) === null` — `fail("skills/<id>: meta.json.auto нерозпізнане — очікується \"завжди\" або непорожній масив правил")` і `skillOk = false`.
68
- 6. Якщо після всіх перевірок цього скіла `skillOk === true`, фіксується `pass("skills/<id>: meta.json валідний")`.
69
- 7. Після проходу всіх скілів повертається `Promise.resolve(reporter.getExitCode())`.
70
-
71
- **Side effects:**
72
-
73
- - читання файлової системи (`existsSync`, `readdirSync`) — синхронне;
74
- - мутація стану внутрішнього звітника (`createCheckReporter()`) через `pass(...)` / `fail(...)`;
75
- - запис у `stdout`/`stderr` залежить від реалізації `check-reporter` (зазвичай агрегує повідомлення для подальшого виводу викликачем);
76
- - **не змінює** жодних файлів і **не** створює директорій.
77
-
78
- **Поведінкові інваріанти:**
79
-
80
- - Відсутність `npm/skills/` — не помилка, а явний `pass` (модуль працює і в репо-споживачі).
81
- - Невалідний `meta.json` зупиняє подальші перевірки конкретного скіла (`continue`), але **не зупиняє** обхід інших скілів.
82
- - Прихований запис (назва починається з `.`) ігнорується, тож `.DS_Store` чи `.tmp` не плутають перевірку.
83
- - Перевірка детермінована: результат залежить тільки від вмісту `npm/skills/` у `cwd`.
84
-
85
- ## Залежності
86
-
87
- ### Стандартна бібліотека Node.js
88
-
89
- | Модуль | Імпортовані символи | Використання |
90
- | ----------- | --------------------------- | -------------------------------------------------------------------- |
91
- | `node:fs` | `existsSync`, `readdirSync` | перевірка наявності `npm/skills/`, `auto.md`; читання списку скілів. |
92
- | `node:path` | `join` | побудова крос-платформних шляхів до каталогів і файлів. |
93
-
94
- ### Внутрішні модулі проєкту
95
-
96
- | Модуль | Імпортовані символи | Використання |
97
- | ----------------------------------------- | ---------------------------------------- | --------------------------------------------------------------------------- |
98
- | `../../../scripts/lib/check-reporter.mjs` | `createCheckReporter` | створення звітника з API `pass(msg)` / `fail(msg)` / `getExitCode()`. |
99
- | `../../../scripts/lib/skill-meta.mjs` | `readSkillMetaRaw`, `parseSkillAutoSpec` | читання сирого `meta.json` зі скіла; парсинг/валідація специфікації `auto`. |
100
-
101
- ### Контракти зовнішніх модулів (як використовуються в коді)
102
-
103
- - `createCheckReporter()` → об'єкт із методами `pass(message: string)`, `fail(message: string)`, `getExitCode(): number` (`0` якщо не було `fail`, `1` якщо хоч раз був).
104
- - `readSkillMetaRaw(skillDir: string)` → розпарсений об'єкт `meta.json` або falsy (наприклад, `null`) якщо файл відсутній/невалідний.
105
- - `parseSkillAutoSpec(value)` → нормалізована специфікація `auto` або `null`, якщо значення нерозпізнане. Прийнятні форми: рядок `"завжди"` або непорожній масив рядків.
106
-
107
- ## Потік виконання / Використання
108
-
109
- ### Контекст
110
-
111
- Модуль викликається з раннера правил концерну `npm-module` (точка входу `npm/rules/npm-module/js/index.mjs` або аналог). У типовому пайплайні `bun run lint` / `n-cursor check` всі `check`-функції правил зібрані в реєстр і виконуються послідовно; результат об'єднується в загальний код виходу процесу.
112
-
113
- ### Типовий виклик
114
-
115
- ```js
116
- import { check } from './skill_meta.mjs'
117
-
118
- const exitCode = await check() // використає process.cwd()
119
- process.exit(exitCode)
120
- ```
121
-
122
- Або з явним коренем (тести/інтеграція):
123
-
124
- ```js
125
- const exitCode = await check('/abs/path/to/repo-root')
126
- ```
127
-
128
- ### Сценарій 1: репо самого пакета `@nitra/cursor`
129
-
130
- - `npm/skills/` існує, містить кілька скілів (наприклад, `n-docgen/`, `n-fix/`, `mdc-check/`).
131
- - Для кожного скіла читається `meta.json`, перевіряються `worktree` (boolean) і `auto` (опціонально).
132
- - Якщо хоч один скіл має `auto.md`, або відсутній/невалідний `meta.json`, або `worktree` не boolean, або `auto` нерозпізнане — функція повертає `1`.
133
- - Інакше — `0`.
134
-
135
- ### Сценарій 2: проєкт-споживач `@nitra/cursor`
136
-
137
- - `npm/skills/` відсутній (інша файлова структура).
138
- - Функція фіксує `pass(...)`, повертає `0` і не виконує жодної ітерації.
139
- - Це дозволяє правилам пакета транзитивно застосовуватися в чужих проєктах без false-negative.
140
-
141
- ### Сценарій 3: переходова міграція на `meta.json`
142
-
143
- - У скілі лишилася стара пам'ятка-метадані `auto.md` поряд з новим `meta.json`.
144
- - Перевірка явно фейлить такий скіл повідомленням `залишковий auto.md — видали (метадані тепер у meta.json)`.
145
- - Це примушує закрити технічний борг міграції.
146
-
147
- ### Очікуваний формат `meta.json`
148
-
149
- ```json
150
- {
151
- "worktree": true,
152
- "auto": "завжди"
153
- }
154
- ```
155
-
156
- або
157
-
158
- ```json
159
- {
160
- "worktree": false,
161
- "auto": ["n-bun", "n-flow"]
162
- }
163
- ```
164
-
165
- або (мінімально):
12
+ Перевірка стану конфігурації. Файл перевіряє відповідність між полями worktree та requireRoot. Перевірка спирається на конфіги meta.json.
166
13
 
167
- ```json
168
- {
169
- "worktree": false
170
- }
171
- ```
14
+ ## Поведінка
172
15
 
173
- ### Невалідні приклади (будуть зафейлені)
16
+ 1. Перевірка поля worktree
17
+ 2. Перевірка поля auto
18
+ 3. Перевірка поля requireRoot
19
+ 4. Перевірка суперечності between worktree та requireRoot
174
20
 
175
- - відсутній файл `meta.json` → `відсутній або невалідний meta.json`;
176
- - `{"worktree": "yes"}` → `meta.json.worktree має бути boolean`;
177
- - `{"worktree": true, "auto": []}` або `{"worktree": true, "auto": "always"}` → `meta.json.auto нерозпізнане ...`;
178
- - наявний `auto.md` поряд → `залишковий auto.md — видали`.
21
+ ## Публічний API
179
22
 
180
- ### Rebuild Test
23
+ check Валідує всі `npm/skills/<id>/meta.json`.
181
24
 
182
- Перевірка інваріантів модуля (можна виконати вручну для регресії):
25
+ ## Гарантії поведінки
183
26
 
184
- 1. У тимчасовому корені створити порожню директорію без `npm/skills/` → `check(tmp)` має повернути `0` і зафіксувати `pass` про відсутність каталогу.
185
- 2. Створити `npm/skills/foo/meta.json` з валідним вмістом `{"worktree": true}` → `check(tmp)` має повернути `0`.
186
- 3. Замінити `worktree` на рядок (`"true"`) → `check(tmp)` має повернути `1` з повідомленням про boolean.
187
- 4. Додати `npm/skills/foo/auto.md` → `check(tmp)` має повернути `1` з повідомленням про залишковий `auto.md`.
188
- 5. Видалити `meta.json` → `check(tmp)` має повернути `1` з повідомленням про відсутній/невалідний `meta.json`.
189
- 6. Створити `npm/skills/.hidden/` — перевірка має ігнорувати її (повернути `0`, якщо інших скілів немає).
190
- 7. Додати `npm/skills/bar/meta.json` з `{"worktree": false, "auto": "завжди"}` → `pass`; замінити `auto` на `"always"` → `fail` про нерозпізнане `auto`.
27
+ - Read-only: файл не виконує операцій запису у файлову систему.
28
+ - Не звертається до мережі.
@@ -1,114 +1,37 @@
1
1
  ---
2
2
  docgen:
3
3
  source: npm/rules/php/fix.mjs
4
- crc: 12fc1644
4
+ crc: 38cf876b
5
+ score: 100
5
6
  ---
6
7
 
7
- # fix.mjs — правило `php`
8
+ # fix.mjs
8
9
 
9
10
  ## Огляд
10
11
 
11
- Файл `npm/rules/php/fix.mjs` це точка входу правила `php` у системі `@nitra/cursor`. Він виконує дві ролі одночасно:
12
+ Виконує застосування політики JS-занепокоєних до mdc-refs на вхідному контексті прогону та повертає результат.
12
13
 
13
- 1. **Library mode** експортує функцію `run(ctx)`, яку викликає CLI-оркестратор (`cursor.mjs`) під час масового прогону правил. У цьому режимі правило інтегрується у спільний pipeline і використовує загальний `walkCache` та інший контекст оркестратора.
14
- 2. **Standalone mode** — коли файл запускається напряму через `bun rules/php/fix.mjs`, він діє як самостійний CLI-скрипт, що є повним еквівалентом команди `npx @nitra/cursor fix php` (з підтягуванням конфігурації, whitelist і фінальним summary).
14
+ Виконується при запуску через командний рядок, виконуючи повний еквівалент команди `npx @nitra/cursor fix <id>` та повертає код виходу.
15
15
 
16
- Логіка правила (applies → JS-concerns → policy → mdc-refs) інкапсульована у спільному оркестраторі `runStandardRule`, тож сам файл `fix.mjs` залишається мінімальним «glue»-шаром і не містить специфічної для PHP логіки безпосередньо — конкретні чекери лежать поряд у директорії правила (`checks/`, `applies.mjs`, `policy.mjs` тощо), а їх виявлення робить `runStandardRule` за конвенцією шляху `import.meta.dirname`.
16
+ ## Поведінка
17
17
 
18
- ## Експорти / API
18
+ 1. Запуск правила.
19
+ * Приймає контекст прогону.
20
+ * Виконує застосування JS-занепокоєних до політики до mdc-refs.
21
+ * Повертає результат прогону.
19
22
 
20
- | Експорт | Тип | Призначення |
21
- | ------- | ---------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
22
- | `run` | `function(ctx?: RuleContext): Promise<number>` | Іменований експорт — основний entry-point library-режиму. Запускає стандартний pipeline правила в каталозі поточного модуля. Повертає exit-code (0 — OK, 1 — порушення). |
23
+ 2. Запуск у режимі CLI.
24
+ * Виконується при запуску через CLI.
25
+ * Виконує повний еквівалент команди `npx @nitra/cursor fix <id>`.
26
+ * Повертає код виходу.
23
27
 
24
- Файл **не** має `default`-експорту. Side-effect на верхньому рівні модуля: блок `if (isRunAsCli(...))` із викликом `process.exit(...)` — спрацьовує лише при прямому запуску.
28
+ ## Публічний API
25
29
 
26
- ## Функції
30
+ run — запускає правило: applies → JS-concerns → policy → mdc-refs (через runStandardRule).
31
+ Library mode — викликається CLI orchestration через `import + run`.
27
32
 
28
- ### `run(ctx)`
33
+ ## Гарантії поведінки
29
34
 
30
- ```js
31
- export function run(ctx)
32
- ```
33
-
34
- - **Параметри:**
35
- - `ctx` _(опціональний)_ — об'єкт типу `RuleContext`, імпортований з `../../scripts/lib/run-standard-rule.mjs`. Передається оркестратором і містить кеш обходу файлової системи (`walkCache`) та інші розшаровані між правилами дані. Якщо не передано — `runStandardRule` створює власний локальний контекст.
36
- - **Повертає:** `Promise<number>` — exit-code прогону:
37
- - `0` — правило пройшло без порушень;
38
- - `1` — виявлено порушення (або правило завершилось помилкою, яку оркестратор мапить на ненульовий код).
39
- - **Side effects:**
40
- - Делегує всю реальну роботу `runStandardRule`: читання файлів, виконання чекерів, друк summary до `stdout`/`stderr`.
41
- - Сам `run` не має власних побічних ефектів — це тонкий wrapper.
42
- - **Як визначається корінь правила:** через `import.meta.dirname` — абсолютний шлях до директорії, в якій лежить `fix.mjs`. Це дозволяє `runStandardRule` знайти сусідні файли правила (`applies.mjs`, `policy.mjs`, `checks/*.mjs`, `*.mdc` тощо) без додаткових параметрів.
43
-
44
- ## Залежності
45
-
46
- Файл імпортує дві утиліти з внутрішньої бібліотеки `npm/scripts/lib/`:
47
-
48
- | Імпорт | Звідки | Призначення |
49
- | ----------------- | ----------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
50
- | `isRunAsCli` | `../../scripts/lib/run-rule-cli.mjs` | Детектор «чи модуль запущений напряму як CLI». Порівнює `import.meta.url` із `process.argv[1]`. Використовується для гілки standalone. |
51
- | `runRuleCli` | `../../scripts/lib/run-rule-cli.mjs` | Повноцінний CLI-runner правила: парсить аргументи, підтягує config, застосовує whitelist, друкує summary. Повертає `Promise<number>` із exit-кодом. |
52
- | `runStandardRule` | `../../scripts/lib/run-standard-rule.mjs` | Стандартний pipeline правила: послідовно виконує стадії `applies → JS-concerns → policy → mdc-refs`. Приймає шлях до директорії правила та опційний `RuleContext`. |
53
-
54
- Зовнішніх npm-залежностей файл не має — лише внутрішні модулі монорепо.
55
-
56
- ## Потік виконання / Використання
57
-
58
- ### Сценарій A — виклик з оркестратора (library mode)
59
-
60
- 1. CLI `@nitra/cursor fix` (або агрегатор) знаходить правило `php` за його директорією.
61
- 2. Динамічно імпортує `fix.mjs` і викликає `await run(ctx)`, передаючи спільний `RuleContext` (зокрема `walkCache`, щоб уникнути повторного обходу ФС між правилами).
62
- 3. `run` делегує виклик `runStandardRule(import.meta.dirname, ctx)`.
63
- 4. `runStandardRule` повертає exit-code; оркестратор агрегує коди всіх правил.
64
-
65
- ```js
66
- import { run } from '@nitra/cursor/rules/php/fix.mjs'
67
-
68
- const code = await run(sharedCtx)
69
- ```
70
-
71
- ### Сценарій B — прямий запуск файлу (standalone mode)
72
-
73
- 1. Користувач (або IDE/CI) виконує:
74
- ```bash
75
- bun npm/rules/php/fix.mjs
76
- ```
77
- 2. Top-level `if (isRunAsCli(import.meta.url))` повертає `true` (бо `import.meta.url` збігається з шляхом запущеного скрипта).
78
- 3. Викликається `await runRuleCli(import.meta.dirname)` — повноцінний CLI-режим: підвантажує конфігурацію, застосовує whitelist, друкує підсумок.
79
- 4. `process.exit(...)` завершує процес із отриманим exit-кодом, аби CI/IDE могли коректно інтерпретувати результат.
80
-
81
- ### Семантика exit-кодів
82
-
83
- - `0` — правило застосовне та порушень не виявлено (або правило незастосовне для цього проєкту — `applies` повернув `false`).
84
- - `1` — є порушення, які треба виправити.
85
-
86
- ### Коментарі та лінт-винятки
87
-
88
- У standalone-гілці явно вимкнено два правила лінтера:
89
-
90
- ```js
91
- // eslint-disable-next-line n/no-process-exit -- standalone entry-point має повертати exit-code для CI/IDE
92
- process.exit(await runRuleCli(import.meta.dirname))
93
- ```
94
-
95
- Це свідомий виняток: `process.exit` тут потрібний, щоб CLI/CI отримали ненульовий код у разі порушень — без нього процес міг би завершитись із кодом `0` навіть за наявності знайдених проблем.
96
-
97
- ## Архітектурний контекст
98
-
99
- - **Конвенція файлу `fix.mjs`** — у директорії кожного правила (`npm/rules/<id>/fix.mjs`) лежить однотипний тонкий wrapper із двома ролями (library + standalone). Це гарантує:
100
- - єдиний інтерфейс для оркестратора (`run(ctx)`);
101
- - можливість запускати окреме правило ізольовано (для дебагу/CI per-rule).
102
- - **Чому через `import.meta.dirname`** — `runStandardRule` за директорією правила автоматично знаходить усі сусідні артефакти (`applies.mjs`, `policy.mjs`, `checks/*.mjs`, `*.mdc`). Це уникає дублювання id-правила як рядка.
103
- - **Patch-free wrapper** — у самому `fix.mjs` не повинно з'являтися PHP-специфічної логіки; будь-які зміни поведінки правила робляться у сусідніх файлах правила, а не в цьому entry-point'і.
104
-
105
- ## Rebuild Test
106
-
107
- Файл можна повністю відтворити з опису вище за такими інваріантами:
108
-
109
- 1. Два імпорти: `{ isRunAsCli, runRuleCli }` з `../../scripts/lib/run-rule-cli.mjs` і `{ runStandardRule }` з `../../scripts/lib/run-standard-rule.mjs`.
110
- 2. Іменований експорт `function run(ctx)` — однорядкове тіло `return runStandardRule(import.meta.dirname, ctx)`.
111
- 3. JSDoc над `run`: опис стадій (applies → JS-concerns → policy → mdc-refs), згадка library mode, тип параметра `ctx` через `import('...').RuleContext`, тип повернення `Promise<number>` із семантикою 0/1.
112
- 4. Блок `if (isRunAsCli(import.meta.url)) { ... }` із викликом `process.exit(await runRuleCli(import.meta.dirname))` і коментарем-поясненням про дві ролі fix.mjs.
113
- 5. Лінт-disable перед `process.exit`: `n/no-process-exit, unicorn/no-process-exit` із обґрунтуванням «standalone entry-point має повертати exit-code для CI/IDE».
114
- 6. Жодних інших top-level операцій, жодного `default`-експорту.
35
+ - Read-only: файл не виконує операцій запису у файлову систему.
36
+ - Кешує результати в межах одного прогону.
37
+ - Не звертається до мережі.