@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,388 +1,34 @@
1
- # `runtime.mjs` — JS-runtime перевірки правила `js-run.mdc`
1
+ ---
2
+ docgen:
3
+ source: npm/rules/js-run/js/runtime.mjs
4
+ crc: 9c22e999
5
+ score: 90
6
+ ---
2
7
 
3
- ## Огляд
4
-
5
- Модуль `npm/rules/js-run/js/runtime.mjs` — це **виконавча частина** правила `js-run.mdc`
6
- для монорепо-перевірки командою `npx @nitra/cursor check`. Він обходить усі workspace-пакети
7
- (виключаючи кореневий `.`) і для кожного пакета валідує дотримання набору JS-/інфраструктурних
8
- конвенцій, які складно або неможливо виразити лише через Rego-політики per-document.
9
-
10
- Покрите цим модулем:
11
-
12
- - **Заборона `@nitra/bunyan` / `bunyan` в імпортах коду** — статичні `import`, CommonJS
13
- `require`, динамічний `import()`; знаходиться через AST-парсер (`oxc-parser`, делегується
14
- в `../lib/bunyan-imports.mjs`).
15
- - **`OTEL_RESOURCE_ATTRIBUTES` у `k8s/base/configmap.yaml`** — наявність файлу (структуру
16
- валідує Rego через `npx @nitra/cursor fix`, namespace `js_run.configmap`).
17
- - **Внутрішні аліаси `#conn/*`** — імпорти `bun#SQL`, `mssql`, `@nitra/graphql-request#GraphQLClient`
18
- дозволені лише в каталозі `src/conn/` (або в каталозі, заданому `package.json#imports['#conn/*']`).
19
- - **Нейминг і експорти у `#conn/`** — `ql-<id>` / `(pg|mysql|mssql)-(read|write)[-<id>]`;
20
- `export default` заборонений; іменований експорт має дорівнювати camelCase від basename файла;
21
- `index.*` пропускається як reexport-барель.
22
- - **`process.env` / `CheckEnv`** — пряме `process.env.X` заборонене; обов'язкові змінні —
23
- через `env` з `@nitra/check-env` + `checkEnv(['X', …])` у тому ж файлі (або коментар
24
- `// @nitra/cursor ignore-next-line checkEnv`); опційні — через `env` з `node:process`.
25
- - **Паузи через `setTimeout`** — `new Promise(r => setTimeout(r, ms))` має бути замінений на
26
- `await setTimeout(ms)` з `node:timers/promises`.
27
- - **`jsconfig.json` у backend-пакеті з `src/`** — наявність файла (структуру `NodeNext` і
28
- `include: src/**/*` валідує Rego `js_run.jsconfig` через `runConftestBatch`).
29
-
30
- Per-document валідація `package.json` (заборона `@nitra/bunyan`/`bunyan` у залежностях,
31
- правила для `node` у `scripts`) делегована окремому rego-пакету `js_run.package_json` у
32
- `npm/rules/js-run/policy/package_json/`; цей JS-файл — про крос-файлові й AST-перевірки.
33
-
34
- Frontend-пакети (з `vite` у `devDependencies`) повністю пропускаються — для них
35
- актуальний інший контекст (браузерний бандл без `node:process`); bunyan-залежність
36
- такого пакета все одно перевіряється Rego-частиною.
37
-
38
- ## Експорти / API
39
-
40
- | Експорт | Тип | Призначення |
41
- | ------------- | ---------------- | ------------------------------------------------------------------------------------------------------------------- |
42
- | `check(cwd?)` | `async function` | Єдина публічна точка входу. Запускає перевірку всіх workspace-пакетів. Повертає `0` (все OK) або `1` (є порушення). |
43
-
44
- Усі інші функції модуля — внутрішні (без `export`) і використовуються лише з `check`.
45
-
46
- ## Функції
47
-
48
- ### `check(cwd = process.cwd())` _(export)_
49
-
50
- - **Сигнатура:** `async function check(cwd?: string): Promise<number>`
51
- - **Параметри:**
52
- - `cwd` _(string, опційний)_ — абсолютний корінь репозиторію; за замовчуванням
53
- `process.cwd()`.
54
- - **Повертає:** `Promise<number>` — exit-код від `createCheckReporter().getExitCode()`
55
- (0 — успіх, 1 — є хоча б одне `fail(...)`).
56
- - **Side effects:**
57
- - читає `package.json` коренева/workspace-пакетів через `getMonorepoPackageRootDirs`;
58
- - читає `.cursorignore` / конфіг через `loadCursorIgnorePaths`;
59
- - читає файли пакетів (`fs/promises`), синхронні `existsSync` / `statSync`;
60
- - друкує повідомлення `pass(...)` / `fail(...)` через репортер;
61
- - запускає `conftest` через `runConftestBatch` (зовнішній процес) для перевірки `jsconfig.json`.
62
- - **Алгоритм:**
63
- 1. Створює репортер `createCheckReporter()`.
64
- 2. Бере список усіх коренів пакетів і відфільтровує кореневий `.`.
65
- 3. Якщо workspace-пакетів немає — викликає `pass(...)` з відповідним повідомленням
66
- і повертає exit-код.
67
- 4. Завантажує перелік `ignorePaths` (повністю виключені з обходу).
68
- 5. По черзі викликає `checkWorkspacePackage(r, ignorePaths, fail, pass, cwd)` для кожного `r`.
69
- 6. Повертає `reporter.getExitCode()`.
70
-
71
- ### `checkWorkspacePackage(rootDir, ignorePaths, fail, passFn, cwd)`
72
-
73
- - **Сигнатура:**
74
- `async function checkWorkspacePackage(rootDir: string, ignorePaths: string[], fail: (msg: string) => void, passFn: (msg: string) => void, cwd: string): Promise<void>`
75
- - **Параметри:**
76
- - `rootDir` — відносний шлях workspace-пакета (не `'.'`).
77
- - `ignorePaths` — абсолютні шляхи каталогів, виключені з обходу.
78
- - `fail` — callback реєстрації порушення.
79
- - `passFn` — callback повідомлення про успішну під-перевірку.
80
- - `cwd` — корінь репозиторію.
81
- - **Повертає:** `Promise<void>`.
82
- - **Side effects:** читає `package.json` пакета; запускає всі під-перевірки нижче;
83
- для frontend-пакета (vite у `devDependencies`) повертається одразу після `passFn`.
84
- - **Алгоритм:**
85
- 1. Формує `label = '[<rootDir>] '` і `absPackageRoot`.
86
- 2. Завантажує `pkgJson = loadPackageJson(rootDir, cwd)`.
87
- 3. Якщо `packageJsonHasViteDevDependency(pkgJson)` — `passFn(...)` і вихід.
88
- 4. `checkBackendJsconfigWhenSrcPresent(...)` — gate на `jsconfig.json`.
89
- 5. `checkBunyanImports(...)` → якщо `0` порушень, друкує позитивне повідомлення.
90
- 6. `collectSourceFiles(...)` — спільний список JS/TS-файлів для подальших сканів.
91
- 7. `checkConnImports(...)` → позитивне повідомлення з резолвленим `connDir`.
92
- 8. `checkConnFileNamingAndExports(...)` → позитивне повідомлення про канон у `connDir/`.
93
- 9. `checkProcessEnvUsage(...)` → позитивне повідомлення про `process.env`/`checkEnv`.
94
- 10. `checkPromiseSetTimeoutPause(...)` → позитивне повідомлення про `setTimeout`-паузи.
95
- 11. `checkOtelConfigmap(...)` — лише наявність `k8s/base/configmap.yaml`.
96
-
97
- ### `backendPackageHasSrcDir(absPackageRoot)`
98
-
99
- - **Сигнатура:** `function backendPackageHasSrcDir(absPackageRoot: string): boolean`
100
- - **Параметри:** `absPackageRoot` — абсолютний корінь пакета.
101
- - **Повертає:** `true`, якщо `<absPackageRoot>/src` існує і це каталог.
102
- - **Side effects:** синхронний `statSync`; помилки ловить і повертає `false`.
103
-
104
- ### `checkBackendJsconfigWhenSrcPresent(rootDir, absPackageRoot, label, fail, passFn, cwd)`
105
-
106
- - **Сигнатура:**
107
- `function checkBackendJsconfigWhenSrcPresent(rootDir: string, absPackageRoot: string, label: string, fail: (msg: string) => void, passFn: (msg: string) => void, cwd: string): void`
108
- - **Параметри:** як у `checkWorkspacePackage`.
109
- - **Повертає:** `void`.
110
- - **Side effects:** `existsSync` для `jsconfig.json`; виклик `runConftestBatch` (зовнішній
111
- процес `conftest`); виклик `fail`/`passFn`.
112
- - **Алгоритм:**
113
- 1. Якщо `src/` відсутній — повернутися (gate перевірки).
114
- 2. Якщо `jsconfig.json` відсутній — `fail(...)` із повідомленням про канонічний файл і вихід.
115
- 3. Викликає `runConftestBatch({ policyDirRel: 'js-run/jsconfig', namespace: 'js_run.jsconfig', files: [jcPath] })`.
116
- 4. Якщо порушень немає — `passFn(...)`; інакше — `fail(...)` для кожного.
117
-
118
- ### `relPosix(absPackageRoot, absPath)`
119
-
120
- - **Сигнатура:** `function relPosix(absPackageRoot: string, absPath: string): string`
121
- - **Параметри:** корінь пакета й абсолютний шлях до файлу.
122
- - **Повертає:** відносний шлях у posix-форматі (`/`), отриманий заміною `\\` → `/` у результаті
123
- `node:path#relative`.
124
- - **Side effects:** немає (чиста функція).
125
-
126
- ### `checkBunyanImports(absPackageRoot, ignorePaths, label, fail)`
127
-
128
- - **Сигнатура:**
129
- `async function checkBunyanImports(absPackageRoot: string, ignorePaths: string[], label: string, fail: (msg: string) => void): Promise<number>`
130
- - **Повертає:** кількість знайдених порушень.
131
- - **Side effects:** `walkDir` (читання каталогу), `readFile` для кожного source-файла, виклик `fail`.
132
- - **Алгоритм:**
133
- 1. Збирає `sourcePaths` обходом `walkDir`, фільтр: `!shouldSkipFileForBunyanScan(rel) && isBunyanScanSourceFile(rel)`.
134
- 2. Для кожного — читає вміст і викликає `findBunyanImportsInText(content, rel)`.
135
- 3. Для кожного `v` друкує повідомлення з номером рядка, ім'ям модуля й snippet'ом і
136
- інкрементує лічильник.
137
-
138
- ### `collectSourceFiles(absPackageRoot, ignorePaths)`
139
-
140
- - **Сигнатура:**
141
- `async function collectSourceFiles(absPackageRoot: string, ignorePaths: string[]): Promise<string[]>`
142
- - **Повертає:** масив абсолютних шляхів до файлів-кандидатів на скан (фільтр
143
- `isCheckEnvScanSourceFile`).
144
- - **Side effects:** `walkDir`. Зверніть увагу: фільтр базується саме на правилах
145
- `check-env-scan`, але отриманий список потім перевикористовується для інших сканів
146
- (`conn-imports`, `conn-file-rules`, `process-env`, `promise-settimeout`), кожен з яких
147
- має свій додатковий внутрішній фільтр (`isConnImportsScanSourceFile` тощо).
148
-
149
- ### `checkConnImports(absPackageRoot, sourcePaths, pkgJson, label, fail)`
150
-
151
- - **Сигнатура:**
152
- `async function checkConnImports(absPackageRoot: string, sourcePaths: string[], pkgJson: unknown, label: string, fail: (msg: string) => void): Promise<number>`
153
- - **Повертає:** кількість порушень.
154
- - **Side effects:** `readFile`, `fail`.
155
- - **Алгоритм:**
156
- 1. `connDir = resolveConnDirFromPackageJson(pkgJson)`.
157
- 2. Для кожного файла зі `sourcePaths`:
158
- - пропускає, якщо не source-file для conn-imports-scan;
159
- - пропускає, якщо файл вже всередині `connDir/`;
160
- - читає вміст, викликає `findConnFactoryImportsInText(content, rel)` і друкує
161
- повідомлення `fail(...)` із форматуванням `{ <specifier> } from '<module>'` або
162
- `'<module>'` (коли `specifier === '*'`).
163
-
164
- ### `checkConnFileNamingAndExports(absPackageRoot, sourcePaths, pkgJson, label, fail)`
165
-
166
- - **Сигнатура:**
167
- `async function checkConnFileNamingAndExports(absPackageRoot: string, sourcePaths: string[], pkgJson: unknown, label: string, fail: (msg: string) => void): Promise<number>`
168
- - **Повертає:** кількість порушень.
169
- - **Side effects:** `readFile`, `fail`.
170
- - **Алгоритм:** для кожного файла, який `isConnFileToCheck(rel, connDir)`, читає вміст і
171
- для кожного `v` з `findConnFileRuleViolations(content, rel)` друкує повідомлення з
172
- `formatConnFileViolation(v, label, rel, connDir)`.
173
-
174
- ### `isConnFileToCheck(rel, connDir)`
175
-
176
- - **Сигнатура:** `function isConnFileToCheck(rel: string, connDir: string): boolean`
177
- - **Повертає:** `true`, коли файл:
178
- - лежить всередині `connDir/` (`isInsideConnDir`);
179
- - має розширення JS/TS, що відповідає `isConnFileRulesSourceFile`;
180
- - basename **не** починається з `index.` (бо це reexport-барель).
8
+ # runtime.mjs
181
9
 
182
- ### `formatConnFileViolation(v, label, rel, connDir)`
183
-
184
- - **Сигнатура:**
185
- `function formatConnFileViolation(v: { kind: 'name'|'default-export'|'export-name', expectedName?: string, foundNames?: string[] }, label: string, rel: string, connDir: string): string`
186
- - **Повертає:** готовий текст повідомлення для `fail(...)`.
187
- - **Поведінка за `kind`:**
188
- - `'name'` — повідомлення про канон імен (`ql-<id>`, `pg-/mysql-/mssql-{read|write}[-<id>]`,
189
- kebab-case `[a-z0-9-]`).
190
- - `'default-export'` — заборонений `export default` у `connDir/`.
191
- - інше (`'export-name'`) — очікувано `export const <expectedName>`; знайдені імена
192
- показуються через кому, якщо `foundNames` непорожній, інакше тире.
193
-
194
- ### `checkProcessEnvUsage(absPackageRoot, sourcePaths, label, fail)`
195
-
196
- - **Сигнатура:**
197
- `async function checkProcessEnvUsage(absPackageRoot: string, sourcePaths: string[], label: string, fail: (msg: string) => void): Promise<number>`
198
- - **Повертає:** кількість порушень.
199
- - **Side effects:** `readFile`, `fail`.
200
- - **Алгоритм:** для кожного файла читає вміст і викликає `findUncheckedProcessEnvInText`.
201
- Залежно від `v.kind` формує різне повідомлення:
202
- - `'process-env'` — пряме `process.env.X`: підказує замінити на `env` з
203
- `@nitra/check-env` + `checkEnv(['X'])` або з `node:process` (опційно).
204
- - інакше — `env.X` з `@nitra/check-env`, не закритий `checkEnv(['X'])` (або
205
- `// @nitra/cursor ignore-next-line checkEnv`).
206
-
207
- ### `checkPromiseSetTimeoutPause(absPackageRoot, sourcePaths, label, fail)`
208
-
209
- - **Сигнатура:**
210
- `async function checkPromiseSetTimeoutPause(absPackageRoot: string, sourcePaths: string[], label: string, fail: (msg: string) => void): Promise<number>`
211
- - **Повертає:** кількість порушень.
212
- - **Side effects:** `readFile`, `fail`.
213
- - **Алгоритм:** фільтрує файли через `isPromiseSetTimeoutScanSourceFile`, для решти
214
- читає вміст і викликає `findPromiseSetTimeoutInText` — порушення друкуються з
215
- підказкою «`await setTimeout(ms)` з `node:timers/promises`».
216
-
217
- ### `packageJsonHasViteDevDependency(pkgJson)`
218
-
219
- - **Сигнатура:** `function packageJsonHasViteDevDependency(pkgJson: unknown): boolean`
220
- - **Повертає:** `true`, якщо `pkgJson.devDependencies` — об'єкт і має ключ `'vite'`.
221
- - **Side effects:** немає.
222
- - **Семантика:** ідентично `packageJsonLacksViteDevDependency` з `auto-rules.mjs`, але
223
- приймає вже розпарсений об'єкт (без I/O).
224
-
225
- ### `loadPackageJson(rootDir, cwd)`
226
-
227
- - **Сигнатура:** `async function loadPackageJson(rootDir: string, cwd: string): Promise<unknown>`
228
- - **Повертає:** розпарсений `package.json` пакета або `null`, якщо файла немає.
229
- - **Side effects:** `existsSync`, `readFile`, `JSON.parse`.
230
- - **Примітка:** заборону `@nitra/bunyan` / `bunyan` у `dependencies` / `devDependencies`
231
- перенесено в Rego-пакет `npm/policy/js_run/package_json/`; тут залишилась лише AST-перевірка
232
- імпортів.
233
-
234
- ### `checkOtelConfigmap(rootDir, passFn, cwd)`
235
-
236
- - **Сигнатура:**
237
- `function checkOtelConfigmap(rootDir: string, passFn: (msg: string) => void, cwd: string): void`
238
- - **Повертає:** `void`.
239
- - **Side effects:** `existsSync`, `passFn`.
240
- - **Алгоритм:** якщо `<rootDir>/k8s/base/configmap.yaml` існує — друкує повідомлення про
241
- факт наявності й нагадує, що структуру (OTEL-атрибути) перевіряє Rego через
242
- `npx @nitra/cursor fix` → `js_run.configmap`.
243
-
244
- ## Залежності
245
-
246
- ### Node.js стандартна бібліотека
247
-
248
- - `node:fs` — `existsSync`, `statSync` (синхронні перевірки наявності каталогу / файла).
249
- - `node:fs/promises` — `readFile` (читання текстових файлів).
250
- - `node:path` — `join`, `relative` (формування шляхів; `relPosix` додатково нормалізує).
251
-
252
- ### Локальні модулі (`../lib/`)
253
-
254
- - `../lib/bunyan-imports.mjs` — `findBunyanImportsInText`, `isBunyanScanSourceFile`,
255
- `shouldSkipFileForBunyanScan`.
256
- - `../lib/check-env-scan.mjs` — `findUncheckedProcessEnvInText`, `isCheckEnvScanSourceFile`.
257
- - `../lib/conn-file-rules.mjs` — `findConnFileRuleViolations`, `isConnFileRulesSourceFile`.
258
- - `../lib/conn-imports-scan.mjs` — `findConnFactoryImportsInText`, `isConnImportsScanSourceFile`,
259
- `isInsideConnDir`, `resolveConnDirFromPackageJson`.
260
- - `../lib/promise-settimeout-scan.mjs` — `findPromiseSetTimeoutInText`,
261
- `isPromiseSetTimeoutScanSourceFile`.
262
-
263
- ### Скрипти каркасу (`../../../scripts/`)
264
-
265
- - `scripts/lib/check-reporter.mjs` — `createCheckReporter` (репортер `pass`/`fail` +
266
- `getExitCode`).
267
- - `scripts/lib/run-conftest-batch.mjs` — `runConftestBatch` (запуск `conftest` на наборі
268
- файлів, повертає `violations[]`).
269
- - `scripts/lib/load-cursor-config.mjs` — `loadCursorIgnorePaths` (читання списку шляхів
270
- для виключення з обходу).
271
- - `scripts/utils/walkDir.mjs` — `walkDir` (рекурсивний обхід каталогу з callback'ом і
272
- списком ігнорувань).
273
- - `scripts/lib/workspaces.mjs` — `getMonorepoPackageRootDirs` (перелік коренів
274
- workspace-пакетів монорепо).
275
-
276
- ### Зовнішні залежності (через посередників)
277
-
278
- - `conftest` — викликається з `runConftestBatch`; виконує Rego-політики, наприклад
279
- `js_run.jsconfig` із `npm/rules/js-run/policy/jsconfig/`.
280
- - `oxc-parser` — використовується в `bunyan-imports.mjs` для AST-сканування імпортів
281
- (через залежність, не імпортується прямо тут).
282
-
283
- ## Потік виконання / Використання
284
-
285
- ### Точка входу
286
-
287
- Модуль експортує лише `check(cwd?)`, яку викликає диспетчер правил (`@nitra/cursor check`)
288
- для правила `js-run`. Очікуваний контракт — повернути exit-код для агрегації по всіх правилах.
289
-
290
- ### Високорівневий потік
291
-
292
- ```
293
- check(cwd)
294
- └─ createCheckReporter()
295
- └─ getMonorepoPackageRootDirs(cwd) → roots
296
- └─ workspaceRoots = roots.filter(r => r !== '.')
297
- └─ [if empty] pass('немає workspace-пакетів') → return exitCode
298
- └─ loadCursorIgnorePaths(cwd) → ignorePaths
299
- └─ for each r ∈ workspaceRoots:
300
- checkWorkspacePackage(r, ignorePaths, fail, pass, cwd)
301
- ├─ loadPackageJson(r, cwd)
302
- ├─ [if vite-frontend] passFn → return
303
- ├─ checkBackendJsconfigWhenSrcPresent(...)
304
- │ ├─ backendPackageHasSrcDir → gate
305
- │ ├─ [no jsconfig] fail
306
- │ └─ runConftestBatch (Rego: js_run.jsconfig)
307
- ├─ checkBunyanImports(...)
308
- │ ├─ walkDir → sourcePaths (фільтр bunyan-scan)
309
- │ └─ for each → findBunyanImportsInText
310
- ├─ collectSourceFiles(...) → sourcePaths (фільтр check-env)
311
- ├─ checkConnImports(...)
312
- │ └─ resolveConnDirFromPackageJson + findConnFactoryImportsInText
313
- ├─ checkConnFileNamingAndExports(...)
314
- │ ├─ isConnFileToCheck
315
- │ └─ findConnFileRuleViolations → formatConnFileViolation
316
- ├─ checkProcessEnvUsage(...)
317
- │ └─ findUncheckedProcessEnvInText
318
- ├─ checkPromiseSetTimeoutPause(...)
319
- │ └─ findPromiseSetTimeoutInText
320
- └─ checkOtelConfigmap(...) [лише існування k8s/base/configmap.yaml]
321
- └─ return reporter.getExitCode()
322
- ```
323
-
324
- ### Логіка пропусків (gate'и)
325
-
326
- - **Кореневий `.`** workspace відфільтровується одразу.
327
- - **Frontend (vite у `devDependencies`)** — увесь `js-run` пропускається на рівні
328
- workspace.
329
- - **`jsconfig.json`** — перевіряється лише там, де є `src/` каталог.
330
- - **Conn-сканування** — імпорти `bun#SQL` / `mssql` / `@nitra/graphql-request#GraphQLClient`
331
- перевіряються тільки **поза** каталогом `connDir` (а нейминг/експорти — тільки
332
- всередині нього, окрім `index.*`).
333
- - **Bunyan-сканування** — додатково керується `shouldSkipFileForBunyanScan` для специфічних
334
- шляхів і `isBunyanScanSourceFile` для розширень.
335
- - **`k8s/base/configmap.yaml`** — лише наявність; OTEL-атрибути перевіряє Rego.
336
-
337
- ### Як модуль інтегрується із суміжними частинами правила
338
-
339
- - **AST-частина**: бере на себе крос-файлову й AST-логіку, яку складно виразити в Rego.
340
- - **Per-document Rego**: `js_run.package_json` (bunyan/scripts.node), `js_run.configmap`
341
- (OTEL), `js_run.jsconfig` (canonical `compilerOptions`/`include`).
342
- - **JS-оркестрація Rego через `runConftestBatch`**: модуль викликає `conftest` лише там, де
343
- попередній gate (наявність `src/` + наявність `jsconfig.json`) дозволяє це робити —
344
- _Plan B_: Rego-authoritative, JS оркеструє per-package gate.
10
+ ## Огляд
345
11
 
346
- ### Приклад використання
12
+ pgWriteContract перевіряє правила нейминга та експортів для файлів усередині `#conn/`.
13
+ check перевіряє правила js-run.mdc лише для workspace-пакетів.
347
14
 
348
- ```js
349
- import { check } from './runtime.mjs'
15
+ ## Поведінка
350
16
 
351
- const exitCode = await check(process.cwd())
352
- process.exit(exitCode)
353
- ```
17
+ pgWriteContract
18
+ Перевіряє відповідність правил нейминга та експортів для файлів усередині `#conn/`
354
19
 
355
- ### Поведінкові інваріанти
20
+ check
21
+ Перевіряє відповідність правилам js-run.mdc лише для workspace-пакетів
356
22
 
357
- - Будь-який `fail(...)` → exit-code 1.
358
- - Відсутність помилок у під-перевірці → відповідне інформаційне `pass(...)`.
359
- - Frontend-пакет (vite) ніколи не отримує жодного `fail` від цього модуля.
360
- - Кореневий пакет монорепо ніколи не перевіряється цим модулем.
23
+ ## Публічний API
361
24
 
362
- ## Rebuild Test
25
+ - pgWriteContract — записує дані в контракт
26
+ - check — перевіряє дотримання правил js-run.mdc для пакетів у workspace
363
27
 
364
- Документ написано на основі повного читання вихідного файла `runtime.mjs` (446 рядків).
365
- Якщо повністю відновлювати модуль за цим описом, відтворюються:
28
+ ## Гарантії поведінки
366
29
 
367
- - Єдиний експорт `check(cwd?)` та його контракт із `createCheckReporter`.
368
- - Список workspace-фільтрації (`r !== '.'`) та early-return при порожньому списку.
369
- - Виклик `loadCursorIgnorePaths` й передача `ignorePaths` в усі скани.
370
- - Послідовність дев'яти кроків у `checkWorkspacePackage` із саме такими повідомленнями
371
- для `passFn` / `fail`.
372
- - Gate `vite у devDependencies` → пропуск усього `js-run` для frontend-пакета.
373
- - Gate `src/` для `jsconfig.json` та делегування структури до Rego `js_run.jsconfig`
374
- через `runConftestBatch({ policyDirRel: 'js-run/jsconfig', namespace: 'js_run.jsconfig',
375
- files: [jcPath] })`.
376
- - Дев'ять допоміжних функцій (`backendPackageHasSrcDir`, `relPosix`, `checkBunyanImports`,
377
- `collectSourceFiles`, `checkConnImports`, `checkConnFileNamingAndExports`,
378
- `isConnFileToCheck`, `formatConnFileViolation`, `checkProcessEnvUsage`,
379
- `checkPromiseSetTimeoutPause`, `packageJsonHasViteDevDependency`, `loadPackageJson`,
380
- `checkOtelConfigmap`, `checkBackendJsconfigWhenSrcPresent`) із зазначеними сигнатурами,
381
- параметрами й side effects.
382
- - Перелік модулів-залежностей (`../lib/*`, `../../../scripts/lib/*`,
383
- `../../../scripts/utils/walkDir.mjs`) і стандартних модулів Node.js (`node:fs`,
384
- `node:fs/promises`, `node:path`).
385
- - Інваріант, що `collectSourceFiles` використовує фільтр `isCheckEnvScanSourceFile`,
386
- а інші скани мають свої внутрішні фільтри (`isConnImportsScanSourceFile`,
387
- `isPromiseSetTimeoutScanSourceFile`).
388
- - Формат повідомлень `fail(...)` із префіксом `[<pkg>] ` та номером рядка `${rel}:${v.line}`.
30
+ - Read-only: файл не виконує операцій запису у файлову систему.
31
+ - Перехоплює помилки і не пропускає винятків назовні (fail-safe).
32
+ - За невдачі повертає значення помилки (`false`/`null`/`Err`) замість генерування винятку чи паніки.
33
+ - Свідомо пропускає шляхи: `base/`.
34
+ - Не звертається до мережі.
@@ -1,138 +1,33 @@
1
1
  ---
2
2
  docgen:
3
3
  source: npm/rules/k8s/fix.mjs
4
- crc: 12fc1644
4
+ crc: 38cf876b
5
+ score: 100
5
6
  ---
6
7
 
7
- # fix.mjs — точка входу правила `k8s`
8
+ # fix.mjs
8
9
 
9
10
  ## Огляд
10
11
 
11
- Файл `npm/rules/k8s/fix.mjs` це **точка входу правила `k8s`** у системі `@nitra/cursor`. Він виконує дві ролі одночасно:
12
+ Файл надає механізми для виконання визначених правил. Виконання цих правил здійснюється через публічну функцію run. Виконання відбувається у режимі командного рядка.
12
13
 
13
- 1. **Library mode** — експортує функцію `run(ctx)`, яку імпортує верхньорівневий CLI-оркестратор (`@nitra/cursor`) під час прогону групи правил (`fix`/`lint`-команди). У цьому режимі правило отримує спільний контекст прогону (`RuleContext`), що містить, серед іншого, кеш обходу файлової системи (`walkCache`), і має повертати числовий exit-code без виклику `process.exit`.
14
- 2. **Standalone mode** — якщо файл запущено напряму як CLI (`bun rules/k8s/fix.mjs`), він самостійно завантажує конфіг, застосовує whitelist, друкує summary та завершує процес із відповідним exit-code, тобто є повним еквівалентом команди `npx @nitra/cursor fix k8s`.
14
+ ## Поведінка
15
15
 
16
- Сама логіка правила (які саме файли обходити, які `applies`/`JS-concerns`/`policy`/`mdc-refs` перевіряти) у цьому файлі **не описана** — вона делегується універсальному рушію `runStandardRule`, який знаходить артефакти правила за каталогом, переданим через `import.meta.dirname`.
16
+ 1. Запуск правила.
17
+ * Виклик runStandardRule з контекстом.
18
+ * Повернення результату.
17
19
 
18
- Файл є тонкою адаптерною обгорткою — типовий шаблон `fix.mjs`, що повторюється для всіх правил у `npm/rules/<id>/`.
20
+ 2. Запуск правила у режимі CLI.
21
+ * Виклик runRuleCli з директорією модуля.
22
+ * Вихід з процесом залежно від результату.
19
23
 
20
- ## Експорти / API
24
+ ## Публічний API
21
25
 
22
- | Експорт | Тип | Призначення |
23
- | ------- | ---------------------------------------- | ------------------------------------------------------------------------------------------------------ |
24
- | `run` | `(ctx?: RuleContext) => Promise<number>` | Запуск правила в **library mode**. Викликається верхньорівневим CLI під час оркестрації набору правил. |
26
+ run запускає правило: applies → JS-concerns → policy → mdc-refs (через runStandardRule).
27
+ Library mode викликається CLI orchestration через `import + run`.
25
28
 
26
- Файл також має **side-effect блок верхнього рівня** (умовний `process.exit(await runRuleCli(...))`), який спрацьовує **лише** коли модуль є entry-point поточного Node/Bun-процесу. Цей блок не є експортом, але є частиною публічної поведінки файлу як standalone-скрипта.
29
+ ## Гарантії поведінки
27
30
 
28
- Інших іменованих чи default-експортів файл не має.
29
-
30
- ## Функції
31
-
32
- ### `run(ctx)`
33
-
34
- ```js
35
- /**
36
- *
37
- */
38
- export function run(ctx) {
39
- return runStandardRule(import.meta.dirname, ctx)
40
- }
41
- ```
42
-
43
- **Сигнатура:**
44
-
45
- ```ts
46
- function run(ctx?: RuleContext): Promise<number>
47
- ```
48
-
49
- **Параметри:**
50
-
51
- - `ctx` _(опційно)_ — об'єкт контексту прогону типу `RuleContext` (тип реекспортується з `../../scripts/lib/run-standard-rule.mjs`). У контексті, як зазначено в JSDoc, може передаватися, зокрема, `walkCache` — спільний кеш обходу файлової системи між правилами, щоб не сканувати дерево заново для кожного правила в одній сесії. Якщо параметр не передано, `runStandardRule` працює без зовнішнього кешу.
52
-
53
- **Повертає:**
54
-
55
- - `Promise<number>` — exit-code результату прогону правила:
56
- - `0` — OK (порушень немає);
57
- - `1` — знайдено порушення (`runStandardRule` повертає `1`, коли хоча б одна перевірка дала falsy/негативний результат).
58
-
59
- **Side effects:**
60
-
61
- - Делегує всю роботу `runStandardRule`, який, своєю чергою:
62
- - обходить файлову систему за `applies`-патернами правила;
63
- - запускає підмодулі правила (`applies`, `JS-concerns`, `policy`, `mdc-refs`) — у послідовності, визначеній стандартним рушієм;
64
- - пише діагностику/виводить порушення у stdout/stderr (точна форма залежить від рушія, не цього файлу).
65
- - Сама функція `run` не торкається `process.exit`, `process.cwd` чи глобального стану — увесь побічний ефект інкапсульовано всередині `runStandardRule`.
66
-
67
- **Чому передається `import.meta.dirname`:** це абсолютний шлях до каталогу `npm/rules/k8s/`, в якому лежить даний `fix.mjs`. `runStandardRule` за цим шляхом знаходить решту артефактів правила (наприклад, `k8s.mdc`, `applies.mjs`, `check-*.mjs`, `policy`-файли тощо), не вимагаючи від `fix.mjs` явно перераховувати, які саме перевірки треба виконати.
68
-
69
- ### Top-level standalone-блок
70
-
71
- ```js
72
- if (isRunAsCli(import.meta.url)) {
73
- process.exit(await runRuleCli(import.meta.dirname))
74
- }
75
- ```
76
-
77
- **Призначення:** дозволити запускати правило окремо — `bun npm/rules/k8s/fix.mjs` — і отримати такий самий результат, як від `npx @nitra/cursor fix k8s` (із завантаженням конфігу, застосуванням whitelist та друком summary).
78
-
79
- **Поведінка:**
80
-
81
- - `isRunAsCli(import.meta.url)` повертає `true`, якщо поточний файл є entry-point процесу (а не імпортований модуль). Якщо це бібліотечний імпорт — блок не виконується, побічних ефектів немає.
82
- - `runRuleCli(import.meta.dirname)` — повний CLI-цикл одного правила: завантаження конфігу проєкту, фільтр whitelist, виклик `run`-логіки, друк підсумкового summary; повертає `Promise<number>` — exit-code.
83
- - `process.exit(...)` примусово завершує процес із цим exit-code, щоб CI/IDE могли коректно проінтерпретувати результат прогону.
84
-
85
- **Top-level `await`:** доступний у файлі завдяки тому, що `.mjs` є ES-модулем — це обов'язкова умова для коректної роботи `await runRuleCli(...)` поза `async`-функцією.
86
-
87
- **ESLint-директива:** коментар `// eslint-disable-next-line n/no-process-exit, unicorn/no-process-exit` свідомо вимикає правила, що забороняють `process.exit`, тому що standalone entry-point **повинен** повертати exit-code (це і пояснює коментар-`-- ...` після назв правил).
88
-
89
- ## Залежності
90
-
91
- ### Внутрішні
92
-
93
- - `../../scripts/lib/run-rule-cli.mjs` (`npm/scripts/lib/run-rule-cli.mjs`) — імпортуються два named-експорти:
94
- - `isRunAsCli(metaUrl)` — детектор того, чи запущений файл як CLI-entry, а не як імпортований модуль (стандартний ESM-патерн «main module detection» через `import.meta.url`);
95
- - `runRuleCli(ruleDir)` — повний цикл standalone-прогону одного правила (config-loading + whitelist + виклик `run` + summary).
96
- - `../../scripts/lib/run-standard-rule.mjs` (`npm/scripts/lib/run-standard-rule.mjs`) — імпортується:
97
- - `runStandardRule(ruleDir, ctx?)` — універсальний рушій «стандартного» правила, що знаходить за `ruleDir` усі артефакти (`applies`, `JS-concerns`, `policy`, `mdc-refs`) і запускає їх у правильному порядку;
98
- - реекспортує тип `RuleContext` (використовується у JSDoc `@param`).
99
-
100
- ### Зовнішні
101
-
102
- - Глобальні Node-runtime API: `process.exit` (умовний виклик), `import.meta.dirname`, `import.meta.url`. Окремих npm-залежностей цей файл не має.
103
-
104
- ## Потік виконання / Використання
105
-
106
- ### Сценарій 1. Library mode (типове використання)
107
-
108
- 1. Верхньорівневий CLI-оркестратор `@nitra/cursor` (наприклад, команда `fix`) збирає список активних правил.
109
- 2. Для правила `k8s` він робить динамічний імпорт цього файлу (`import('npm/rules/k8s/fix.mjs')`).
110
- 3. Оркестратор формує спільний `ctx: RuleContext` (зокрема `walkCache`, який буде поділено між правилами однієї сесії) і викликає `await mod.run(ctx)`.
111
- 4. `run` делегує виклик `runStandardRule(import.meta.dirname, ctx)`, який:
112
- - читає артефакти правила з каталогу `npm/rules/k8s/`;
113
- - обходить FS відповідно до `applies`-патернів (використовуючи `ctx.walkCache`, якщо переданий);
114
- - послідовно виконує перевірки `applies → JS-concerns → policy → mdc-refs`;
115
- - повертає `0` (OK) або `1` (порушення).
116
- 5. Оркестратор агрегує exit-коди з усіх правил у фінальний exit-code сесії.
117
-
118
- ### Сценарій 2. Standalone mode (запуск одного правила вручну)
119
-
120
- 1. Користувач запускає `bun npm/rules/k8s/fix.mjs` (або еквівалент через інший Node-runtime з підтримкою `import.meta.dirname`).
121
- 2. ESM-завантажувач виконує файл як entry-point: визначення `run` потрапляє у scope модуля, але оркестратор ззовні його не викликає.
122
- 3. Виконується top-level `if (isRunAsCli(import.meta.url))` — умова `true`, оскільки `import.meta.url` збігається з entry-point процесу.
123
- 4. Викликається `await runRuleCli(import.meta.dirname)`:
124
- - підвантажується конфіг проєкту;
125
- - застосовується whitelist (якщо налаштований);
126
- - всередині `runRuleCli` запускається та сама логіка правила (через ту саму експортовану функцію `run` / `runStandardRule`), що й у library mode;
127
- - друкується summary з кількістю перевірених файлів і знайдених порушень.
128
- 5. Отриманий `exit-code` передається в `process.exit(...)` — процес завершується із цим кодом, що дозволяє CI/IDE коректно реагувати на результат.
129
-
130
- ### Сценарій 3. Імпорт як модуля без виклику `run`
131
-
132
- Якщо файл імпортується суто для інтроспекції (`import * as fixK8s from '.../k8s/fix.mjs'`), `isRunAsCli(import.meta.url)` поверне `false` (`import.meta.url` модуля не співпаде з URL entry-point процесу), і standalone-блок не виконається. Жодних побічних ефектів імпорт не має — це **безпечно** для тулзів типу docgen чи статичного аналізу.
133
-
134
- ### Замітки про шаблон
135
-
136
- - Файл є **взаємозамінним** із аналогічними `fix.mjs` у сусідніх каталогах `npm/rules/<id>/` — відрізняється лише розташуванням (а отже — `import.meta.dirname`), і завдяки цьому той самий рушій `runStandardRule` обслуговує всі правила без копіювання логіки.
137
- - Жодна k8s-специфічна логіка тут **не** жорстко закодована — вона лежить у сусідніх файлах правила (`k8s.mdc`, `applies.mjs`, `check-*.mjs`, `policy`-артефакти), які знаходить `runStandardRule` за каталогом.
138
- - Для додавання нового правила достатньо створити каталог `npm/rules/<new-id>/` і покласти туди такий самий `fix.mjs` — без жодних модифікацій (за умови, що структура артефактів стандартна).
31
+ - Read-only: файл не виконує операцій запису у файлову систему.
32
+ - Кешує результати в межах одного прогону.
33
+ - Не звертається до мережі.