@nitra/cursor 12.8.2 → 12.8.4

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 (136) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/bin/n-cursor.js +1 -1
  3. package/package.json +1 -1
  4. package/rules/js/docs/index.md +3 -3
  5. package/rules/js/docs/main.md +6 -6
  6. package/rules/js/js/docs/check.md +12 -17
  7. package/rules/js/js/docs/index.md +4 -4
  8. package/rules/js/js/docs/tooling.md +8 -8
  9. package/rules/js/js/docs/utils_imports.md +21 -200
  10. package/rules/npm-module/js/docs/index.md +5 -5
  11. package/rules/npm-module/js/docs/rule_meta.md +13 -13
  12. package/rules/npm-module/js/docs/skill_meta.md +19 -9
  13. package/rules/npm-module/js/rule_meta.mjs +9 -9
  14. package/rules/npm-module/js/skill_meta.mjs +6 -6
  15. package/rules/{style-lint → style}/docs/fix.md +1 -1
  16. package/rules/{style-lint → style}/docs/index.md +3 -3
  17. package/rules/{style-lint → style}/docs/main.md +1 -1
  18. package/rules/{style-lint → style}/js/docs/index.md +3 -3
  19. package/rules/{style-lint → style}/js/docs/tooling.md +3 -3
  20. package/rules/{style-lint → style}/js/tooling.mjs +1 -1
  21. package/rules/{style-lint/style-lint.mdc → style/main.mdc} +3 -3
  22. package/rules/{style-lint → style}/policy/lint_style_yml/lint_style_yml.rego +2 -2
  23. package/rules/{style-lint → style}/policy/lint_style_yml/template/lint-style.yml.snippet.yml +1 -1
  24. package/rules/{style-lint → style}/policy/package_json/package_json.rego +3 -3
  25. package/rules/{style-lint → style}/policy/vscode_extensions/vscode_extensions.rego +2 -2
  26. package/rules/{style-lint → style}/policy/vscode_settings/vscode_settings.rego +2 -2
  27. package/rules/test/js/docs/index.md +7 -7
  28. package/rules/test/js/docs/stryker_config.md +18 -35
  29. package/rules/test/js/docs/vitest-config-pool-forks.md +14 -12
  30. package/schemas/v8r-catalog.json +4 -4
  31. package/scripts/docs/index.md +16 -16
  32. package/scripts/docs/sync-setup-bun-deps-action.md +13 -14
  33. package/scripts/lib/check-mdc-template-refs.mjs +2 -2
  34. package/scripts/lib/docs/check-mdc-template-refs.md +12 -214
  35. package/scripts/lib/docs/gha-workflow.md +1 -1
  36. package/scripts/lib/docs/index.md +36 -36
  37. package/scripts/lib/docs/mirror-parity.md +18 -157
  38. package/scripts/lib/docs/rule-meta.md +19 -22
  39. package/scripts/lib/docs/run-rule.md +11 -11
  40. package/scripts/lib/docs/skill-meta.md +17 -19
  41. package/scripts/lib/docs/timing-summary.md +6 -6
  42. package/scripts/lib/gha-workflow.mjs +1 -1
  43. package/scripts/lib/mirror-parity.mjs +1 -1
  44. package/scripts/lib/rule-meta.mjs +1 -1
  45. package/scripts/lib/run-rule.mjs +4 -4
  46. package/scripts/lib/skill-meta.mjs +1 -1
  47. package/scripts/utils/docs/index.md +14 -14
  48. package/scripts/utils/docs/resolve-js-root.md +12 -13
  49. /package/rules/abie/{meta.json → main.json} +0 -0
  50. /package/rules/abie/{abie.mdc → main.mdc} +0 -0
  51. /package/rules/adr/{meta.json → main.json} +0 -0
  52. /package/rules/adr/{adr.mdc → main.mdc} +0 -0
  53. /package/rules/bun/{meta.json → main.json} +0 -0
  54. /package/rules/bun/{bun.mdc → main.mdc} +0 -0
  55. /package/rules/capacitor/{meta.json → main.json} +0 -0
  56. /package/rules/capacitor/{capacitor.mdc → main.mdc} +0 -0
  57. /package/rules/changelog/{meta.json → main.json} +0 -0
  58. /package/rules/changelog/{changelog.mdc → main.mdc} +0 -0
  59. /package/rules/ci4/{meta.json → main.json} +0 -0
  60. /package/rules/ci4/{ci4.mdc → main.mdc} +0 -0
  61. /package/rules/doc-files/{meta.json → main.json} +0 -0
  62. /package/rules/doc-files/{doc-files.mdc → main.mdc} +0 -0
  63. /package/rules/docker/{meta.json → main.json} +0 -0
  64. /package/rules/docker/{docker.mdc → main.mdc} +0 -0
  65. /package/rules/efes/{meta.json → main.json} +0 -0
  66. /package/rules/efes/{efes.mdc → main.mdc} +0 -0
  67. /package/rules/feedback/{meta.json → main.json} +0 -0
  68. /package/rules/feedback/{feedback.mdc → main.mdc} +0 -0
  69. /package/rules/ga/{meta.json → main.json} +0 -0
  70. /package/rules/ga/{ga.mdc → main.mdc} +0 -0
  71. /package/rules/graphql/{meta.json → main.json} +0 -0
  72. /package/rules/graphql/{graphql.mdc → main.mdc} +0 -0
  73. /package/rules/hasura/{meta.json → main.json} +0 -0
  74. /package/rules/hasura/{hasura.mdc → main.mdc} +0 -0
  75. /package/rules/image-avif/{meta.json → main.json} +0 -0
  76. /package/rules/image-avif/{image-avif.mdc → main.mdc} +0 -0
  77. /package/rules/image-compress/{meta.json → main.json} +0 -0
  78. /package/rules/image-compress/{image-compress.mdc → main.mdc} +0 -0
  79. /package/rules/js/{meta.json → main.json} +0 -0
  80. /package/rules/js/{js.mdc → main.mdc} +0 -0
  81. /package/rules/js-bun-db/{meta.json → main.json} +0 -0
  82. /package/rules/js-bun-db/{js-bun-db.mdc → main.mdc} +0 -0
  83. /package/rules/js-bun-redis/{meta.json → main.json} +0 -0
  84. /package/rules/js-bun-redis/{js-bun-redis.mdc → main.mdc} +0 -0
  85. /package/rules/js-mssql/{meta.json → main.json} +0 -0
  86. /package/rules/js-mssql/{js-mssql.mdc → main.mdc} +0 -0
  87. /package/rules/js-run/{meta.json → main.json} +0 -0
  88. /package/rules/js-run/{js-run.mdc → main.mdc} +0 -0
  89. /package/rules/k8s/{meta.json → main.json} +0 -0
  90. /package/rules/k8s/{k8s.mdc → main.mdc} +0 -0
  91. /package/rules/nginx-default-tpl/{meta.json → main.json} +0 -0
  92. /package/rules/nginx-default-tpl/{nginx-default-tpl.mdc → main.mdc} +0 -0
  93. /package/rules/npm-module/{meta.json → main.json} +0 -0
  94. /package/rules/npm-module/{npm-module.mdc → main.mdc} +0 -0
  95. /package/rules/php/{meta.json → main.json} +0 -0
  96. /package/rules/php/{php.mdc → main.mdc} +0 -0
  97. /package/rules/python/{meta.json → main.json} +0 -0
  98. /package/rules/python/{python.mdc → main.mdc} +0 -0
  99. /package/rules/rego/{meta.json → main.json} +0 -0
  100. /package/rules/rego/{rego.mdc → main.mdc} +0 -0
  101. /package/rules/release/{meta.json → main.json} +0 -0
  102. /package/rules/release/{release.mdc → main.mdc} +0 -0
  103. /package/rules/rust/{meta.json → main.json} +0 -0
  104. /package/rules/rust/{rust.mdc → main.mdc} +0 -0
  105. /package/rules/security/{meta.json → main.json} +0 -0
  106. /package/rules/security/{security.mdc → main.mdc} +0 -0
  107. /package/rules/{style-lint/meta.json → style/main.json} +0 -0
  108. /package/rules/{style-lint → style}/main.mjs +0 -0
  109. /package/rules/{style-lint → style}/policy/lint_style_yml/target.json +0 -0
  110. /package/rules/{style-lint → style}/policy/package_json/target.json +0 -0
  111. /package/rules/{style-lint → style}/policy/package_json/template/package.json.snippet.json +0 -0
  112. /package/rules/{style-lint → style}/policy/vscode_extensions/target.json +0 -0
  113. /package/rules/{style-lint → style}/policy/vscode_extensions/template/extensions.json.snippet.json +0 -0
  114. /package/rules/{style-lint → style}/policy/vscode_settings/target.json +0 -0
  115. /package/rules/{style-lint → style}/policy/vscode_settings/template/settings.json.snippet.json +0 -0
  116. /package/rules/tauri/{meta.json → main.json} +0 -0
  117. /package/rules/tauri/{tauri.mdc → main.mdc} +0 -0
  118. /package/rules/test/{meta.json → main.json} +0 -0
  119. /package/rules/test/{test.mdc → main.mdc} +0 -0
  120. /package/rules/text/{meta.json → main.json} +0 -0
  121. /package/rules/text/{text.mdc → main.mdc} +0 -0
  122. /package/rules/tool-surface/{meta.json → main.json} +0 -0
  123. /package/rules/tool-surface/{tool-surface.mdc → main.mdc} +0 -0
  124. /package/rules/vue/{meta.json → main.json} +0 -0
  125. /package/rules/vue/{vue.mdc → main.mdc} +0 -0
  126. /package/rules/worktree/{meta.json → main.json} +0 -0
  127. /package/rules/worktree/{worktree.mdc → main.mdc} +0 -0
  128. /package/skills/adr-normalize/{meta.json → main.json} +0 -0
  129. /package/skills/coverage-fix/{meta.json → main.json} +0 -0
  130. /package/skills/doc-aggregate/{meta.json → main.json} +0 -0
  131. /package/skills/doc-files/{meta.json → main.json} +0 -0
  132. /package/skills/lint/{meta.json → main.json} +0 -0
  133. /package/skills/llm-patch/{meta.json → main.json} +0 -0
  134. /package/skills/publish-telegram/{meta.json → main.json} +0 -0
  135. /package/skills/start-check/{meta.json → main.json} +0 -0
  136. /package/skills/taze/{meta.json → main.json} +0 -0
@@ -3,224 +3,22 @@ type: JS Module
3
3
  title: check-mdc-template-refs.mjs
4
4
  resource: npm/scripts/lib/check-mdc-template-refs.mjs
5
5
  docgen:
6
- crc: 17b81322
6
+ crc: c116210e
7
+ model: omlx/gemma-4-e4b-it-OptiQ-4bit
8
+ score: 100
7
9
  ---
8
10
 
9
- Модуль `check-mdc-template-refs.mjs` — це невелика утиліта, призначена для перевірки цілісності посилань між файлом правила `<id>.mdc` та шаблонами, що лежать у підкаталогах `template/` цього самого правила. Він обходить структуру каталогів правила (`fix/<concern>/template/`, `policy/<concern>/template/`), збирає всі знайдені файли й порівнює їхні відносні шляхи з вмістом основного файлу правила `<id>.mdc`. Результатом є перелік шаблонних файлів, на які у `.mdc` немає жодного markdown-посилання, тобто «осиротілі» (orphaned) шаблони.
11
+ ## Огляд
10
12
 
11
- Типовий контекст застосування: модуль використовується в утилітах перевірки/лінтингу правил репозиторію (`npm/rules/<id>/`), де `.mdc`-файл описує правило людською мовою й має посилатися на свої шаблони. Якщо шаблон існує, але не згаданий у `.mdc`, цей модуль повідомить про нього, щоб супровідник правила або додав посилання, або видалив зайвий шаблон.
13
+ Визначає список файлів шаблонів, що знаходяться у каталогах `fix` та `policy`, які не є цільовими посиланнями у файлі `<id>.mdc` як markdown link targets. Це дозволяє ідентифікувати ресурси шаблонів, які не були згадані в контексті правила.
12
14
 
13
- Модуль повністю асинхронний (використовує `node:fs/promises`), стандартної залежності від сторонніх бібліотек не має, працює у середовищі Node.js (а також сумісне з Bun) як ES-модуль (`.mjs`).
15
+ ## Поведінка
14
16
 
15
- ## Експорти / API
17
+ 1. Збирає абсолютні шляхи всіх файлів, що знаходяться у каталогах `template` всередині підкаталогів `fix` та `policy` у вказаному каталозі правила.
18
+ 2. Зчитує вміст файлу `main.mdc` у каталозі правила.
19
+ 3. Фільтрує зібрані шляхи, залишаючи лише ті, які не з'являються у вмісті `main.mdc` у вигляді посилання Markdown (`./<шлях>` або ``).
20
+ 4. Повертає відносні шляхи цих незгаданих шаблонних файлів відносно каталогу правила.
16
21
 
17
- Модуль експортує єдину функцію:
22
+ ## Гарантії поведінки
18
23
 
19
- - `findMissingMdcRefs(ruleDir, ruleId)` публічний експорт (`export async function`).
20
-
21
- Дві внутрішні (не експортовані) допоміжні функції:
22
-
23
- - `walkTemplateDirs(ruleDir)` — обходить підкаталоги `fix/*/template/` і `policy/*/template/`.
24
- - `collectFiles(dir)` — рекурсивно збирає всі файли в заданому каталозі.
25
-
26
- Імпорти з ядра Node:
27
-
28
- - `existsSync` з `node:fs` — синхронна перевірка існування шляху.
29
- - `readdir`, `readFile`, `stat` з `node:fs/promises` — асинхронні операції з файловою системою.
30
- - `join`, `relative` з `node:path` — нормалізація та побудова шляхів.
31
-
32
- ## Функції
33
-
34
- ### findMissingMdcRefs
35
-
36
- Сигнатура:
37
-
38
- ```
39
- export async function findMissingMdcRefs(ruleDir, ruleId): Promise<string[]>
40
- ```
41
-
42
- Параметри:
43
-
44
- - `ruleDir` — `string`, абсолютний шлях до каталогу правила (за конвенцією `npm/rules/<id>/`).
45
- - `ruleId` — `string`, basename правила (наприклад, `"security"`). Використовується для побудови імені `.mdc`-файлу: `${ruleId}.mdc`.
46
-
47
- Що робить:
48
-
49
- 1. Будує очікуваний шлях до файлу правила: `mdcPath = join(ruleDir, `${ruleId}.mdc`)`.
50
- 2. Якщо файл `.mdc` не існує — повертає порожній масив `[]` (нічого перевіряти).
51
- 3. Читає текст `.mdc` у пам'ять як UTF-8 рядок.
52
- 4. Викликає `walkTemplateDirs(ruleDir)`, щоб отримати масив усіх файлів із `template/`-каталогів правила (як шляхи, відносні до `ruleDir`).
53
- 5. Фільтрує отриманий масив, залишаючи лише ті файли, посилань на які НЕ виявлено в тексті `.mdc`. Перевірка наявності посилання — підрядкова: файл вважається «посиланим», якщо в тексті `.mdc` зустрічається будь-яке з двох вкраплень:
54
- - `./<rel>` — типова форма markdown-посилання `[label](./path)`.
55
- - `(<rel>)` — також зловить голу форму `(path)` у круглих дужках.
56
-
57
- Повертає:
58
-
59
- - `Promise<string[]>` — масив відносних шляхів (відносно `ruleDir`) файлів шаблонів, на які в `.mdc` немає посилання.
60
-
61
- Side effects:
62
-
63
- - Виключно read-only доступ до файлової системи: `existsSync`, `readFile`, `readdir`, `stat`. Файли або каталоги не створюються, не змінюються, не видаляються.
64
- - Не виводить нічого в `stdout`/`stderr`. Не має побічних ефектів на process state.
65
-
66
- Помилки:
67
-
68
- - Може кинути помилку, якщо `readFile`/`readdir`/`stat` зазнають невдачі з причин, відмінних від «файл не існує» (наприклад, права доступу). Перед читанням існування `mdcPath` перевіряється явно, тому відсутність `.mdc` помилки не дає.
69
-
70
- ### walkTemplateDirs (внутрішня)
71
-
72
- Сигнатура:
73
-
74
- ```
75
- async function walkTemplateDirs(ruleDir): Promise<string[]>
76
- ```
77
-
78
- Параметри:
79
-
80
- - `ruleDir` — `string`, абсолютний шлях до каталогу правила.
81
-
82
- Що робить:
83
-
84
- 1. Ітерується по двох жорстко закодованих «kind»-категоріях: `'fix'` та `'policy'`.
85
- 2. Для кожного `kind` будує шлях `kindDir = join(ruleDir, kind)`. Якщо такого каталогу немає — пропускає.
86
- 3. Для кожного `concern` (підкаталога або файлу всередині `kindDir`, який повертає `readdir`) будує шлях `tpl = join(kindDir, concern, 'template')`.
87
- 4. Якщо `tpl` не існує — пропускає. Якщо існує, але не є каталогом (`stat(tpl).isDirectory() === false`) — також пропускає.
88
- 5. Викликає `collectFiles(tpl)` для рекурсивного збору всіх файлів і додає їх до результуючого масиву.
89
- 6. На виході перетворює абсолютні шляхи у шляхи, відносні до `ruleDir` (`relative(ruleDir, p)`).
90
-
91
- Повертає:
92
-
93
- - `Promise<string[]>` — відносні (від `ruleDir`) шляхи всіх файлів у `fix/*/template/` і `policy/*/template/`.
94
-
95
- Side effects:
96
-
97
- - Лише read-only ФС-операції.
98
-
99
- Примітка: значення `readdir(kindDir)` (без `withFileTypes`) повертає масив імен і файлів, і каталогів. Перевірка `existsSync(tpl)` та `stat(tpl).isDirectory()` коректно відсіює випадки, коли `concern` — це файл, а не каталог.
100
-
101
- ### collectFiles (внутрішня)
102
-
103
- Сигнатура:
104
-
105
- ```
106
- async function collectFiles(dir): Promise<string[]>
107
- ```
108
-
109
- Параметри:
110
-
111
- - `dir` — `string`, абсолютний шлях каталогу, який треба обійти.
112
-
113
- Що робить:
114
-
115
- 1. Викликає `readdir(dir, { withFileTypes: true })` і отримує `Dirent[]`.
116
- 2. Для кожного запису будує повний шлях `full = join(dir, entry.name)`.
117
- 3. Якщо запис — каталог (`entry.isDirectory()`), рекурсивно занурюється в нього й приєднує знайдене до результату.
118
- 4. Якщо запис — файл (або symlink/інше, що НЕ каталог), додає `full` як є.
119
-
120
- Повертає:
121
-
122
- - `Promise<string[]>` — абсолютні шляхи всіх файлів усередині `dir` (з усіх рівнів вкладеності).
123
-
124
- Side effects:
125
-
126
- - Read-only обхід ФС.
127
-
128
- Зауваження щодо поведінки: символьні посилання й сокети не каталогізуються як директорії (`isDirectory()` поверне `false`), отже потрапляють у список як «файли». Гранична глибина рекурсії не обмежена — для зацикленої структури symlinks теоретично можливе нескінченне занурення; на практиці шаблонні каталоги правил такого не мають.
129
-
130
- ## Залежності
131
-
132
- Стандартна бібліотека Node.js (ESM):
133
-
134
- - `node:fs` — `existsSync` (синхронна перевірка існування).
135
- - `node:fs/promises` — `readdir`, `readFile`, `stat` (асинхронні ФС-операції).
136
- - `node:path` — `join`, `relative` (нормалізація шляхів).
137
-
138
- Зовнішніх npm-залежностей немає. Модуль не використовує жодних глобальних змінних, конфігів, env-vars чи CLI-аргументів. Не звертається до мережі.
139
-
140
- Передумови оточення:
141
-
142
- - Node.js версія, що підтримує ES Modules (`.mjs`) і `node:`-protocol-imports (Node 14+; на практиці Node 18+/Bun).
143
- - Доступ на читання до каталогу `ruleDir` та його підкаталогів.
144
-
145
- ## Потік виконання / Використання
146
-
147
- ### Очікувана структура каталогу правила
148
-
149
- Модуль розрахований на конвенцію розкладки правил:
150
-
151
- ```
152
- <ruleDir>/
153
- <ruleId>.mdc ← текст правила з markdown-посиланнями
154
- fix/
155
- <concern-A>/
156
- template/
157
- file1.ext
158
- nested/file2.ext
159
- <concern-B>/
160
- template/
161
- ...
162
- policy/
163
- <concern-C>/
164
- template/
165
- ...
166
- ```
167
-
168
- Перелічуються лише файли всередині `fix/*/template/` і `policy/*/template/`. Будь-який інший контент (`check-*.mjs`, `README`, інші підкаталоги) ігнорується.
169
-
170
- ### Алгоритм у двох словах
171
-
172
- 1. Зібрати всі файли з `fix/*/template/` і `policy/*/template/`, перетворити у відносні шляхи від `ruleDir`.
173
- 2. Прочитати `<ruleId>.mdc`.
174
- 3. Для кожного відносного шляху перевірити, чи зустрічається в тексті `.mdc` хоча б одна з форм `./<rel>` або `(<rel>)`. Якщо НЕ зустрічається — додати у вихідний список.
175
-
176
- ### Типове використання
177
-
178
- ```js
179
- import { findMissingMdcRefs } from './check-mdc-template-refs.mjs'
180
-
181
- const missing = await findMissingMdcRefs('/abs/path/to/npm/rules/security', 'security')
182
- if (missing.length > 0) {
183
- console.error('Orphaned template files (no markdown link in .mdc):')
184
- for (const rel of missing) console.error(` - ${rel}`)
185
- process.exit(1)
186
- }
187
- ```
188
-
189
- Цей виклик часто є частиною check-скрипта правила (`check-<id>.mjs`) або агрегованого валідатора, який обходить усі правила репозиторію.
190
-
191
- ### Граничні випадки
192
-
193
- - `.mdc` відсутній — повертається `[]`. Це навмисно: правило без `.mdc` не валідуємо «на покинуті шаблони».
194
- - Каталоги `fix/`, `policy/`, `template/` відсутні — обходяться silent, результат для них порожній.
195
- - Шаблонів немає взагалі — повертається `[]`.
196
- - `.mdc` посилається на шаблон, якого фізично немає, — цей сценарій модуль НЕ перевіряє (зворотний напрям перевірки тут не реалізовано).
197
- - Перевірка посилань — підрядкова, без парсингу markdown. Якщо файл містить `./foo/bar.md` як випадковий збіг у документації, шаблон `foo/bar.md` буде вважатися посиланим, навіть якщо це не власне markdown-link. На практиці це не проблема, бо шляхи всередині `template/` достатньо унікальні.
198
- - Сепаратор шляхів — платформозалежний (`path.join`/`path.relative` використовують `\` на Windows). Усередині `.mdc` посилання, як правило, пишуть зі слешем `/` — на Windows це може давати хибно-позитивні результати (тобто файл буде вважатися «без посилання»). У цільовому оточенні (macOS/Linux/Docker) проблема не виникає.
199
-
200
- ### Складність
201
-
202
- - Час: O(N + M), де N — сумарна кількість файлів у `template/`-каталогах, а M — довжина тексту `.mdc` (через `String.prototype.includes`, що виконується для кожного з N файлів двічі).
203
- - Пам'ять: лінійна щодо розміру `.mdc` плюс масиву шляхів.
204
-
205
- ## Rebuild Test
206
-
207
- Файл `check-mdc-template-refs.mjs` можна повністю відновити, дотримуючись опису вище, якщо забезпечити такі властивості:
208
-
209
- 1. ES-модуль (`.mjs`), без `default export`. Єдиний `export` — `async function findMissingMdcRefs(ruleDir, ruleId)`.
210
- 2. Імпорти лише з `node:fs` (`existsSync`), `node:fs/promises` (`readdir`, `readFile`, `stat`) і `node:path` (`join`, `relative`).
211
- 3. Дві внутрішні async-функції: `walkTemplateDirs(ruleDir)` та `collectFiles(dir)`.
212
- 4. `walkTemplateDirs` ітерується по двох категоріях у фіксованому порядку: спочатку `'fix'`, потім `'policy'`. Пропускає неіснуючі `kindDir`. Для кожного `concern` перевіряє існування й те, що `template` — каталог; у разі успіху делегує до `collectFiles`. На виході конвертує абсолютні шляхи у відносні від `ruleDir`.
213
- 5. `collectFiles` використовує `readdir(dir, { withFileTypes: true })`, рекурсивно занурюється тільки в каталоги, інші записи додає в результат як абсолютні шляхи.
214
- 6. `findMissingMdcRefs` спочатку перевіряє існування `<ruleId>.mdc`, читає його у UTF-8, отримує всі файли через `walkTemplateDirs`, потім фільтрує, залишаючи лише ті `rel`, для яких у тексті `.mdc` ОДНОЧАСНО немає `./<rel>` і немає `(<rel>)` (логічне AND через подвійне заперечення з `||` під `!`).
215
- 7. Поведінка строго read-only: жодних запитів у мережу, жодного запису на диск, жодного консольного виводу.
216
- 8. Повертає `Promise<string[]>`, відносні шляхи (з POSIX/платформозалежним сепаратором у міру `path.relative`).
217
-
218
- Тестові сценарії для smoke-перевірки:
219
-
220
- - Каталог без `.mdc` → `[]`.
221
- - `.mdc` є, але `fix/`, `policy/` відсутні → `[]`.
222
- - `fix/x/template/a.txt` існує, у `.mdc` згадано `./fix/x/template/a.txt` → `[]`.
223
- - Той самий шаблон, але `.mdc` посилається як `(fix/x/template/a.txt)` (без `./`) → `[]`.
224
- - Той самий шаблон, але в `.mdc` посилання немає → `['fix/x/template/a.txt']`.
225
- - Вкладений `fix/x/template/sub/b.txt`, посилання немає → містить `'fix/x/template/sub/b.txt'`.
226
- - Запис `concern`, що насправді є файлом, а не каталогом → пропускається без помилки.
24
+ - Read-only: не виконує операцій запису (ФС/БД).
@@ -3,7 +3,7 @@ type: JS Module
3
3
  title: gha-workflow.mjs
4
4
  resource: npm/scripts/lib/gha-workflow.mjs
5
5
  docgen:
6
- crc: d73b42f2
6
+ crc: 952d34d4
7
7
  model: omlx/gemma-4-e4b-it-OptiQ-4bit
8
8
  score: 100
9
9
  ---
@@ -6,40 +6,40 @@ resource: npm/scripts/lib/
6
6
 
7
7
  # npm/scripts/lib
8
8
 
9
- | Файл | Тип |
10
- | --------------------------------------------------------------------------- | --------- |
11
- | [assert-project-root.mjs](assert-project-root.md) | JS Module |
12
- | [changed-files.mjs](changed-files.md) | JS Module |
13
- | [check-mdc-template-refs.mjs](check-mdc-template-refs.md) | JS Module |
14
- | [check-reporter.mjs](check-reporter.md) | JS Module |
15
- | [diff-added-lines.mjs](diff-added-lines.md) | JS Module |
9
+ | Файл | Тип |
10
+ |---|---|
11
+ | [assert-project-root.mjs](assert-project-root.md) | JS Module |
12
+ | [changed-files.mjs](changed-files.md) | JS Module |
13
+ | [check-mdc-template-refs.mjs](check-mdc-template-refs.md) | JS Module |
14
+ | [check-reporter.mjs](check-reporter.md) | JS Module |
15
+ | [diff-added-lines.mjs](diff-added-lines.md) | JS Module |
16
16
  | [discover-check-rules-from-cursor.mjs](discover-check-rules-from-cursor.md) | JS Module |
17
- | [discover-checkable-rules.mjs](discover-checkable-rules.md) | JS Module |
18
- | [ensure-tool.mjs](ensure-tool.md) | JS Module |
19
- | [generated-markdown.mjs](generated-markdown.md) | JS Module |
20
- | [gha-workflow.mjs](gha-workflow.md) | JS Module |
21
- | [inline-template-links.mjs](inline-template-links.md) | JS Module |
22
- | [list-project-rules-mdc.mjs](list-project-rules-mdc.md) | JS Module |
23
- | [list-rule-ids.mjs](list-rule-ids.md) | JS Module |
24
- | [load-cursor-config.mjs](load-cursor-config.md) | JS Module |
25
- | [mirror-parity.mjs](mirror-parity.md) | JS Module |
26
- | [read-n-cursor-config-lite.mjs](read-n-cursor-config-lite.md) | JS Module |
27
- | [resolve-target-files.mjs](resolve-target-files.md) | JS Module |
28
- | [root-notice.mjs](root-notice.md) | JS Module |
29
- | [rule-meta-helpers.mjs](rule-meta-helpers.md) | JS Module |
30
- | [rule-meta.mjs](rule-meta.md) | JS Module |
31
- | [rule-predicates.mjs](rule-predicates.md) | JS Module |
32
- | [run-conftest-batch.mjs](run-conftest-batch.md) | JS Module |
33
- | [run-lint-step.mjs](run-lint-step.md) | JS Module |
34
- | [run-lint.mjs](run-lint.md) | JS Module |
35
- | [run-rule-cli.mjs](run-rule-cli.md) | JS Module |
36
- | [run-rule.mjs](run-rule.md) | JS Module |
37
- | [run-standard-lint.mjs](run-standard-lint.md) | JS Module |
38
- | [run-standard-rule.mjs](run-standard-rule.md) | JS Module |
39
- | [skill-meta.mjs](skill-meta.md) | JS Module |
40
- | [sync-gitignore-worktree.mjs](sync-gitignore-worktree.md) | JS Module |
41
- | [template.mjs](template.md) | JS Module |
42
- | [timing-summary.mjs](timing-summary.md) | JS Module |
43
- | [workspaces.mjs](workspaces.md) | JS Module |
44
- | [worktree-notice.mjs](worktree-notice.md) | JS Module |
45
- | [worktree.mjs](worktree.md) | JS Module |
17
+ | [discover-checkable-rules.mjs](discover-checkable-rules.md) | JS Module |
18
+ | [ensure-tool.mjs](ensure-tool.md) | JS Module |
19
+ | [generated-markdown.mjs](generated-markdown.md) | JS Module |
20
+ | [gha-workflow.mjs](gha-workflow.md) | JS Module |
21
+ | [inline-template-links.mjs](inline-template-links.md) | JS Module |
22
+ | [list-project-rules-mdc.mjs](list-project-rules-mdc.md) | JS Module |
23
+ | [list-rule-ids.mjs](list-rule-ids.md) | JS Module |
24
+ | [load-cursor-config.mjs](load-cursor-config.md) | JS Module |
25
+ | [mirror-parity.mjs](mirror-parity.md) | JS Module |
26
+ | [read-n-cursor-config-lite.mjs](read-n-cursor-config-lite.md) | JS Module |
27
+ | [resolve-target-files.mjs](resolve-target-files.md) | JS Module |
28
+ | [root-notice.mjs](root-notice.md) | JS Module |
29
+ | [rule-meta-helpers.mjs](rule-meta-helpers.md) | JS Module |
30
+ | [rule-meta.mjs](rule-meta.md) | JS Module |
31
+ | [rule-predicates.mjs](rule-predicates.md) | JS Module |
32
+ | [run-conftest-batch.mjs](run-conftest-batch.md) | JS Module |
33
+ | [run-lint-step.mjs](run-lint-step.md) | JS Module |
34
+ | [run-lint.mjs](run-lint.md) | JS Module |
35
+ | [run-rule-cli.mjs](run-rule-cli.md) | JS Module |
36
+ | [run-rule.mjs](run-rule.md) | JS Module |
37
+ | [run-standard-lint.mjs](run-standard-lint.md) | JS Module |
38
+ | [run-standard-rule.mjs](run-standard-rule.md) | JS Module |
39
+ | [skill-meta.mjs](skill-meta.md) | JS Module |
40
+ | [sync-gitignore-worktree.mjs](sync-gitignore-worktree.md) | JS Module |
41
+ | [template.mjs](template.md) | JS Module |
42
+ | [timing-summary.mjs](timing-summary.md) | JS Module |
43
+ | [workspaces.mjs](workspaces.md) | JS Module |
44
+ | [worktree-notice.mjs](worktree-notice.md) | JS Module |
45
+ | [worktree.mjs](worktree.md) | JS Module |
@@ -3,171 +3,32 @@ type: JS Module
3
3
  title: mirror-parity.mjs
4
4
  resource: npm/scripts/lib/mirror-parity.mjs
5
5
  docgen:
6
- crc: 15dc336a
6
+ crc: d2140a00
7
+ model: omlx/gemma-4-e4b-it-OptiQ-4bit
8
+ score: 100
7
9
  ---
8
10
 
9
- Модуль `mirror-parity.mjs` забезпечує перевірку парності (parity) між «дзеркальними» файлами правил Cursor у `.cursor/rules/n-<id>.mdc` та їх канонічними джерелами у `npm/rules/<id>/<id>.mdc`. Ідея така: репозиторій містить два представлення одного й того ж правила:
11
+ ## Огляд
10
12
 
11
- - канонічне джерело правила лежить у `npm/rules/<id>/<id>.mdc` (з можливими посиланнями на шаблони у тій самій теці);
12
- - дзеркало лежить у `.cursor/rules/n-<id>.mdc` і повинно бути результатом застосування трансформу `inlineTemplateLinks` до канону (тобто посилання на шаблони мають бути вставлені «інлайном»).
13
+ Модуль забезпечує паралельність (parity) дзеркал правил. Він порівнює вміст дзеркала `.cursor/rules/n-<id>.mdc` з канонічним вмістом `npm/rules/<id>/<id>.mdc`, який містить вбудовані шаблони (inlined-шаблони). Це гарантує, що локальні копії правил відповідають централізованим, трансформованим версіям, виявляючи дрейф, що виникає при зміні канонічного `.mdc` без регенерації дзеркала.
13
14
 
14
- Коли канонічний `.mdc` змінюють і забувають регенерувати дзеркало, виникає «дрейф» (drift). Цей модуль:
15
+ ## Поведінка
15
16
 
16
- - перелічує керовані дзеркала (ті, для яких знайдено канон);
17
- - обчислює очікуваний вміст дзеркала через ту саму трансформацію, що і синхронізатор;
18
- - виявляє ідентифікатори дрейфних правил (де `actual ≠ expected`).
17
+ listManagedMirrors
18
+ Визначає список керованих дзеркал правил, які мають канонічне джерело у `npm/rules`.
19
19
 
20
- Модуль використовується одночасно і як гард у тестах (очікувано `drift === []`), і для разової регенерації дзеркал. Контекст беклогу — адаптація flow #10.
20
+ expectedMirrorContent
21
+ Формує очікуваний вміст дзеркала, застосовуючи трансформацію до канонічного вмісту.
21
22
 
22
- ## Експорти / API
23
+ findMirrorDrift
24
+ Виявляє і повертає список ідентифікаторів дзеркал, вміст яких відрізняється від очікуваного канонічного.
23
25
 
24
- Модуль експортує три іменовані функції:
26
+ ## Публічний API
25
27
 
26
- - `listManagedMirrors(repoRoot)`синхронна; повертає опис керованих дзеркал.
27
- - `expectedMirrorContent(canonicalPath)`асинхронна (повертає `Promise<string>`); обчислює очікуваний вміст дзеркала.
28
- - `findMirrorDrift(repoRoot)`асинхронна; повертає масив id правил із дрейфом, відсортований за зростанням.
28
+ listManagedMirrors — перераховує дзеркала, які мають визначене основне джерело, і ігнорує зовнішні.
29
+ expectedMirrorContent — визначає, яким має бути вміст дзеркала, використовуючи основне джерело з вбудованими шаблонами.
30
+ findMirrorDrift — виявляє ідентифікатори дзеркал, чий фактичний вміст відрізняється від очікуваного.
29
31
 
30
- Жодних дефолтних експортів, побічних ефектів на рівні модуля немає (лише імпорти стандартних модулів і одного локального).
32
+ ## Гарантії поведінки
31
33
 
32
- ## Функції
33
-
34
- ### `listManagedMirrors(repoRoot)`
35
-
36
- Сигнатура: `function listManagedMirrors(repoRoot: string): { id: string, mirrorPath: string, canonicalPath: string }[]`
37
-
38
- Параметри:
39
-
40
- - `repoRoot` — абсолютний шлях до кореня репозиторію (директорія, у якій лежать `.cursor/` та `npm/`).
41
-
42
- Повертає масив об'єктів-описів дзеркал, де:
43
-
44
- - `id` — ідентифікатор правила без префіксу `n-` і без розширення `.mdc` (наприклад, для файлу `n-bun.mdc` → `bun`);
45
- - `mirrorPath` — абсолютний шлях до файлу дзеркала всередині `.cursor/rules/`;
46
- - `canonicalPath` — абсолютний шлях до канонічного `.mdc` всередині `npm/rules/<id>/`.
47
-
48
- Алгоритм:
49
-
50
- 1. Будує шлях до `.cursor/rules`.
51
- 2. Якщо такої директорії не існує (`existsSync` false) — повертає порожній масив (раннє повернення, безпечне для свіжих репо).
52
- 3. Зчитує перелік файлів директорії синхронно (`readdirSync`).
53
- 4. Фільтрує файли: повинні починатися з префіксу `'n-'` (константа `MIRROR_PREFIX`) і завершуватися розширенням `'.mdc'` (константа `MDC_EXT`).
54
- 5. Мапить кожен файл у об'єкт із обчисленими шляхами: `id` отримується вирізанням префіксу і розширення (`f.slice(MIRROR_PREFIX.length, -MDC_EXT.length)`).
55
- 6. Залишає лише ті записи, для яких реально існує канонічне джерело `canonicalPath` (друга фільтрація через `existsSync`). Це дозволяє пропускати «зовнішні» дзеркала, які не мають канону в монорепо.
56
-
57
- Side effects: лише читання директорії з диску (синхронні `existsSync`, `readdirSync`). Жодних записів, мережевих викликів, мутацій глобального стану.
58
-
59
- Помилки: якщо файлова система кине помилку під час `readdirSync` (наприклад, права доступу) — вона прокинеться вгору; для типового сценарію відсутності директорії `.cursor/rules` функція не падає (гард через `existsSync`).
60
-
61
- ### `expectedMirrorContent(canonicalPath)`
62
-
63
- Сигнатура: `function expectedMirrorContent(canonicalPath: string): Promise<string>`
64
-
65
- Параметри:
66
-
67
- - `canonicalPath` — абсолютний шлях до канонічного `.mdc`-файлу (`npm/rules/<id>/<id>.mdc`).
68
-
69
- Повертає `Promise<string>` — очікуваний (нормалізований) текст дзеркала після інлайнінгу шаблонів. Хоча сама функція не використовує `async`/`await`, її результат типізовано як `Promise`, оскільки делегує виклик до `inlineTemplateLinks`, яка є асинхронною (її результат може бути thenable). Це означає, що споживач має `await`-нути повернене значення.
70
-
71
- Алгоритм:
72
-
73
- 1. Синхронно зчитує вміст канонічного файлу як UTF-8 (`readFileSync(canonicalPath, 'utf8')`).
74
- 2. Викликає `inlineTemplateLinks(content, dirname(canonicalPath))`, передаючи прочитаний текст та теку канону як base для розв'язання шляхів до шаблонів.
75
- 3. Повертає результат трансформації.
76
-
77
- Side effects: одне читання з диску. Подальша поведінка щодо шаблонів інкапсульована в `inlineTemplateLinks` (див. її документацію). Контракт: цей же самий трансформ застосовує синк, тому очікуваний вміст детермінований по канону.
78
-
79
- Помилки: якщо файл за `canonicalPath` не існує або недоступний — `readFileSync` кине помилку. Викличні сторони мають гарантувати існування (`listManagedMirrors` уже фільтрує неіснуючі канони).
80
-
81
- ### `findMirrorDrift(repoRoot)`
82
-
83
- Сигнатура: `async function findMirrorDrift(repoRoot: string): Promise<string[]>`
84
-
85
- Параметри:
86
-
87
- - `repoRoot` — абсолютний шлях до кореня репозиторію.
88
-
89
- Повертає `Promise<string[]>` — відсортований за зростанням масив `id` правил, де дзеркало розійшлося з очікуваним вмістом.
90
-
91
- Алгоритм:
92
-
93
- 1. Заводить порожній масив `drift`.
94
- 2. Послідовно (через `for...of`) обходить усі керовані дзеркала, отримані з `listManagedMirrors(repoRoot)`.
95
- 3. Для кожного дзеркала `m`:
96
- - `await`-ить очікуваний вміст через `expectedMirrorContent(m.canonicalPath)`;
97
- - синхронно зчитує фактичний вміст файлу дзеркала `readFileSync(m.mirrorPath, 'utf8')`;
98
- - якщо стрічки не дорівнюють — додає `m.id` до `drift`.
99
- 4. Повертає `drift.sort()` (лексикографічне сортування).
100
-
101
- Side effects: тільки читання з диску. Не записує жодних файлів, не пише в лог.
102
-
103
- Зауваження щодо порівняння: рівність стрічок є точною (строге `!==` по UTF-8 тексту). Будь-яка різниця в пробілах, символах кінця рядка чи порядку інлайнених шаблонів буде розцінена як дрейф.
104
-
105
- ## Залежності
106
-
107
- Стандартна бібліотека Node.js:
108
-
109
- - `node:fs` — `existsSync`, `readdirSync`, `readFileSync`. Усі виклики синхронні. Імпорт зроблено через `node:`-префікс для явної прив'язки до built-in модуля.
110
- - `node:path` — `dirname`, `join`. Використовуються для безпечного складання абсолютних шляхів і отримання батьківської теки канону.
111
-
112
- Локальні модулі:
113
-
114
- - `./inline-template-links.mjs` — імпорт іменованої функції `inlineTemplateLinks(content, baseDir)`. Це той самий трансформ, що його використовує синк дзеркал; саме завдяки спільному використанню досягається консистентність між «гардом дрейфу» і «генератором дзеркал».
115
-
116
- Зовнішніх npm-залежностей немає.
117
-
118
- Константи на рівні модуля:
119
-
120
- - `MIRROR_PREFIX = 'n-'` — префікс імені файлів дзеркал.
121
- - `MDC_EXT = '.mdc'` — розширення файлів правил Cursor.
122
-
123
- ## Потік виконання / Використання
124
-
125
- Типові сценарії використання модуля:
126
-
127
- 1. Тест-гард парності (CI). Споживач передає корінь репо й перевіряє, що дрейф порожній:
128
-
129
- ```js
130
- import { findMirrorDrift } from './mirror-parity.mjs'
131
-
132
- const drift = await findMirrorDrift(repoRoot)
133
- if (drift.length) {
134
- throw new Error(`Mirror drift detected for: ${drift.join(', ')}`)
135
- }
136
- ```
137
-
138
- 2. Разова регенерація дзеркал. Споживач отримує список керованих дзеркал і для кожного перезаписує файл дзеркала очікуваним вмістом:
139
-
140
- ```js
141
- import { writeFileSync } from 'node:fs'
142
- import { listManagedMirrors, expectedMirrorContent } from './mirror-parity.mjs'
143
-
144
- for (const m of listManagedMirrors(repoRoot)) {
145
- const expected = await expectedMirrorContent(m.canonicalPath)
146
- writeFileSync(m.mirrorPath, expected)
147
- }
148
- ```
149
-
150
- (Сам модуль `mirror-parity.mjs` записів не виконує — це задача викличного скрипта.)
151
-
152
- Внутрішній потік виконання `findMirrorDrift`:
153
-
154
- 1. Виклик `listManagedMirrors(repoRoot)`:
155
- - перевірка існування `.cursor/rules`;
156
- - читання списку файлів;
157
- - фільтрація за префіксом `n-` і розширенням `.mdc`;
158
- - обчислення `id`, `mirrorPath`, `canonicalPath`;
159
- - відкидання дзеркал без канону.
160
- 2. Послідовний обхід отриманих описів:
161
- - читання канону → `inlineTemplateLinks` → очікуваний текст;
162
- - читання дзеркала → порівняння;
163
- - накопичення id з дрейфом.
164
- 3. Сортування результату та повернення.
165
-
166
- Контрактна гарантія: якщо синк використовує ту ж саму функцію `inlineTemplateLinks` для генерації дзеркал, то регенерація закриває будь-який дрейф, виявлений `findMirrorDrift`. Якщо дрейф виявлено — він завжди вказує на людську помилку (зміна канону без регенерації) або на розбіжність версій трансформу.
167
-
168
- Обмеження:
169
-
170
- - Обхід послідовний (без `Promise.all`) — простіший контракт по помилках, але повільніший на великих наборах правил. Зважаючи на типову кількість правил у `.cursor/rules`, це не критично.
171
- - Усі читання файлів синхронні, попри асинхронну сигнатуру `findMirrorDrift` — асинхронність зумовлена тільки інтерфейсом `inlineTemplateLinks`.
172
- - Префікс `n-` зашитий константою — додавання інших префіксів дзеркал вимагатиме зміни модуля.
173
- - Зовнішні дзеркала (без канону в `npm/rules/<id>/`) автоматично пропускаються; модуль не повідомляє про них окремо.
34
+ - Read-only: не виконує операцій запису (ФС/БД).
@@ -3,36 +3,33 @@ type: JS Module
3
3
  title: rule-meta.mjs
4
4
  resource: npm/scripts/lib/rule-meta.mjs
5
5
  docgen:
6
- crc: fa5ca866
6
+ crc: 36aea8cb
7
+ model: omlx/gemma-4-e4b-it-OptiQ-4bit
8
+ score: 100
7
9
  ---
8
10
 
9
- Цей файл парсує метадані правил npm/rules/<id>/meta.json для автоматичного виявлення проблемних місць у коді. Він визначає, коли правило має бути активним, використовуючи різні специфікації, такі як завжди-ввімкнене правило, правило, яке активується після виявлення залежностей, або правило, яке активується на основі glob-шаблонів чи незводимих предикатів. Це дозволяє системі динамічно визначати та застосовувати правила, не потребуючи явного налаштування.
11
+ ## Огляд
12
+
13
+ Парсер інтерпретує метадані правил, що знаходяться у `npm/rules/<id>/meta.json`. Він реалізує data-driven логіку для визначення умов активації кожного детектора. Специфікації активації (`auto`) нормалізуються на основі вмісту `meta.json`, підтримуючи чотири типи: константа `RULE_ALWAYS` ("завжди"), залежності від інших правил, шаблони за допомогою `glob`, або незводимі предикати. Парсер не виконує операцій запису у файлову систему чи бази даних і забезпечує безпечну роботу, перехоплюючи помилки.
10
14
 
11
15
  ## Поведінка
12
16
 
13
- `RULE_ALWAYS`: визначає літерал для активації правила "завжди".
14
- `parseRuleAutoSpec`: нормалізує значення `meta.json.auto` у дискриміновану форму.
15
- `parseRuleLintPhase`: нормалізує значення `meta.json.lint` у фазу lint.
16
- `readRuleMetaRaw`: читає та парсить `meta.json` одного правила, повертаючи об’єкт або `null`.
17
+ RULE_ALWAYS константа, що позначає безумовну активацію правила.
18
+ parseRuleAutoSpec Нормалізує значення поля `auto` з метаданих правила у дискриміновану специфікацію активації.
19
+ parseRuleLintSpec Нормалізує значення поля `lint` з метаданих правила у специфікацію області застосування детектора.
20
+ readRuleMetaRaw Читає та парсить вміст `main.json` з каталогу правила, повертаючи його як об'єкт або `null` у разі помилки чи відсутності файлу.
17
21
 
18
22
  ## Публічний API
19
23
 
20
- - RULE_ALWAYS — Активує правило.
21
- - parseRuleAutoSpec — Перетворює значення `meta.json.auto` на конкретну опцію.
22
- - parseRuleLintPhase Перетворює значення `meta.json.lint` на фазу lint.
23
- - readRuleMetaRaw Зчитує та аналізує файл `meta.json` правила.
24
+ RULE_ALWAYS — константа, що вказує на безумовну активацію.
25
+ parseRuleAutoSpec — перетворює налаштування автоматичного визначення правил з `meta.json` у структурований формат.
26
+ parseRuleLintSpecперетворює налаштування лінтування з `meta.json` у визначення області дії детектора.
27
+ "per-file"визначає, що детектор працює з окремими зміненими файлами (порівняння змін з оригіналом).
28
+ "full" — вказує на повний, нероздільний аналіз між усіма файлами (активується лише при використанні прапорця `--full` або в CI).
29
+ readRuleMetaRaw — зчитує та обробляє метадані одного правила з файлу `meta.json`.
24
30
 
25
31
  ## Гарантії поведінки
26
32
 
27
- - `RULE_ALWAYS` повертає `true` якщо правило активне.
28
- - `parseRuleAutoSpec` повертає `true` якщо специфікація правила успішно розібрана.
29
- - `parseRuleAutoSpec` повертає `false` якщо специфікація правила не може бути розібрана.
30
- - `parseRuleLintPhase` повертає `true` якщо правило успішно розібрано на етапі linting.
31
- - `parseRuleLintPhase` повертає `false` якщо правило не може бути розібрано на етапі linting.
32
- - `readRuleMetaRaw` повертає `true` якщо метадані правила успішно прочитані.
33
- - `readRuleMetaRaw` повертає `false` якщо метадані правила не можуть бути прочитані.
34
- - У разі невдачі, функція повертає `false` або `null`.
35
- - Функції не кидають винятків.
36
- - Немає кешування.
37
- - Немає гарантій щодо стану файлів або каталогів.
38
- - Поля `worktree` правила не використовуються.
33
+ - Read-only: не виконує операцій запису (ФС/БД).
34
+ - Перехоплює помилки і не пропускає винятків назовні (fail-safe).
35
+ - За певних помилок повертає порожнє значення (напр. `null`) замість винятку.