@nitra/cursor 5.1.0 → 5.2.1

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 (214) hide show
  1. package/.claude-template/settings.template.json +22 -0
  2. package/.pi-template/extensions/n-cursor-adr/docs/index.md +15 -9
  3. package/CHANGELOG.md +18 -1
  4. package/bin/n-cursor.js +73 -16
  5. package/docs/stryker.config.md +6 -0
  6. package/docs/vitest.config.md +6 -0
  7. package/lib/docs/llm.md +29 -0
  8. package/lib/docs/models.md +24 -17
  9. package/lib/docs/omlx.md +32 -0
  10. package/lib/llm.mjs +137 -0
  11. package/lib/omlx.mjs +49 -4
  12. package/package.json +1 -1
  13. package/rules/abie/docs/fix.md +6 -0
  14. package/rules/abie/js/docs/applies.md +6 -0
  15. package/rules/abie/js/docs/env_dns.md +25 -22
  16. package/rules/abie/js/docs/firebase_hosting.md +6 -0
  17. package/rules/abie/js/docs/hc_pairing.md +21 -25
  18. package/rules/abie/js/docs/ua_http_route.md +27 -19
  19. package/rules/abie/js/docs/ua_node_selector.md +24 -19
  20. package/rules/abie/lib/docs/enabled.md +13 -7
  21. package/rules/abie/lib/docs/env-dns.md +9 -3
  22. package/rules/abie/lib/docs/hc-yaml.md +6 -0
  23. package/rules/abie/lib/docs/http-route.md +6 -0
  24. package/rules/abie/lib/docs/k8s-tree.md +6 -0
  25. package/rules/abie/lib/docs/kustomization-patches.md +6 -0
  26. package/rules/abie/lib/docs/overlay-paths.md +6 -0
  27. package/rules/abie/lib/docs/yaml.md +6 -0
  28. package/rules/adr/docs/fix.md +6 -0
  29. package/rules/adr/js/docs/hooks.md +29 -244
  30. package/rules/bun/docs/fix.md +6 -0
  31. package/rules/bun/js/docs/layout.md +37 -375
  32. package/rules/capacitor/docs/fix.md +22 -108
  33. package/rules/capacitor/js/docs/platforms.md +62 -268
  34. package/rules/changelog/docs/fix.md +6 -0
  35. package/rules/changelog/js/docs/consistency.md +36 -383
  36. package/rules/changelog/lib/docs/package-manifest.md +6 -0
  37. package/rules/ci4/docs/fix.md +23 -165
  38. package/rules/ci4/js/docs/marksman_config.md +9 -1
  39. package/rules/docker/docs/fix.md +6 -0
  40. package/rules/docker/js/docs/lint.md +55 -239
  41. package/rules/docker/lib/docs/docker-hadolint.md +6 -0
  42. package/rules/docker/lib/docs/docker-mirror.md +6 -0
  43. package/rules/docker/lib/docs/docker-native-addon.md +6 -0
  44. package/rules/docker/lib/docs/docker-nginx-user.md +6 -0
  45. package/rules/docker/lint/docs/lint.md +9 -1
  46. package/rules/efes/docs/fix.md +6 -0
  47. package/rules/feedback/docs/fix.md +21 -131
  48. package/rules/ga/docs/fix.md +14 -12
  49. package/rules/ga/js/docs/lint.md +12 -9
  50. package/rules/ga/js/docs/workflows.md +20 -19
  51. package/rules/ga/lint/docs/lint.md +6 -0
  52. package/rules/graphql/docs/fix.md +6 -0
  53. package/rules/graphql/js/docs/tooling.md +18 -253
  54. package/rules/graphql/lib/docs/graphql-gql-scan.md +6 -0
  55. package/rules/hasura/docs/fix.md +18 -111
  56. package/rules/image-avif/docs/fix.md +6 -0
  57. package/rules/image-avif/js/docs/avif_generation.md +6 -0
  58. package/rules/js-bun-db/lib/docs/bun-sql-scan.md +9 -3
  59. package/rules/js-bun-redis/lib/docs/redis-imports.md +6 -0
  60. package/rules/js-lint/js/docs/utils_imports.md +6 -0
  61. package/rules/js-lint-ci/docs/fix.md +7 -1
  62. package/rules/js-mssql/docs/fix.md +6 -0
  63. package/rules/js-mssql/lib/docs/mssql-pool-scan.md +6 -0
  64. package/rules/js-run/docs/fix.md +6 -0
  65. package/rules/js-run/lib/docs/bunyan-imports.md +6 -0
  66. package/rules/js-run/lib/docs/check-env-scan.md +6 -0
  67. package/rules/js-run/lib/docs/conn-file-rules.md +6 -0
  68. package/rules/js-run/lib/docs/conn-imports-scan.md +6 -0
  69. package/rules/js-run/lib/docs/promise-settimeout-scan.md +6 -0
  70. package/rules/js-run/lib/docs/temporal-scan.md +6 -0
  71. package/rules/k8s/docs/fix.md +6 -0
  72. package/rules/k8s/lint/docs/lint.md +6 -0
  73. package/rules/nginx-default-tpl/docs/fix.md +6 -0
  74. package/rules/npm-module/js/docs/header_doc_pointer.md +7 -0
  75. package/rules/npm-module/js/header_doc_pointer.mjs +2 -8
  76. package/rules/php/docs/fix.md +6 -0
  77. package/rules/php/lint/docs/lint.md +6 -0
  78. package/rules/python/docs/fix.md +6 -0
  79. package/rules/python/lint/docs/lint.md +6 -0
  80. package/rules/rego/lint/docs/lint.md +6 -0
  81. package/rules/release/docs/change.md +6 -0
  82. package/rules/release/docs/fix.md +6 -0
  83. package/rules/release/docs/release.md +6 -0
  84. package/rules/release/lib/docs/aggregate.md +6 -0
  85. package/rules/release/lib/docs/change-file.md +6 -0
  86. package/rules/release/lib/docs/fallback.md +6 -0
  87. package/rules/rust/lib/docs/has-cargo-toml.md +6 -0
  88. package/rules/security/docs/fix.md +7 -1
  89. package/rules/security/js/docs/lint.md +6 -0
  90. package/rules/style-lint/docs/fix.md +6 -0
  91. package/rules/tauri/docs/fix.md +6 -0
  92. package/rules/test/docs/fix.md +6 -0
  93. package/rules/test/js/data/stryker_config/docs/stryker-vue-macros-ignorer.md +6 -0
  94. package/rules/test/js/data/stryker_config/docs/stryker.config.baseline.md +6 -0
  95. package/rules/test/js/data/stryker_config/docs/stryker.config.vue.baseline.md +6 -0
  96. package/rules/test/js/data/vitest_config/docs/vitest.config.baseline.md +6 -0
  97. package/rules/text/docs/fix.md +6 -0
  98. package/rules/text/lint/docs/lint.md +6 -0
  99. package/rules/text/lint/docs/run-dotenv-linter.md +6 -0
  100. package/rules/text/lint/docs/run-shellcheck.md +6 -0
  101. package/rules/text/lint/docs/run-v8r.md +6 -0
  102. package/rules/vue/lib/docs/vue-forbidden-imports.md +6 -0
  103. package/scripts/coverage-classify/cache.mjs +1 -1
  104. package/scripts/coverage-classify/docs/apply.md +6 -0
  105. package/scripts/coverage-classify/docs/cache.md +6 -0
  106. package/scripts/coverage-classify/docs/prompt.md +6 -0
  107. package/scripts/coverage-classify/docs/verdict-schema.md +6 -0
  108. package/scripts/coverage-classify/prompt.mjs +1 -1
  109. package/scripts/coverage-fix-extract.mjs +1 -1
  110. package/scripts/coverage-fix.mjs +2 -1
  111. package/scripts/docs/auto-skills.md +6 -0
  112. package/scripts/docs/build-agents-commands.md +7 -1
  113. package/scripts/docs/cli-entry.md +6 -0
  114. package/scripts/docs/coverage-fix-extract.md +6 -0
  115. package/scripts/docs/coverage-fix.md +6 -0
  116. package/scripts/docs/ensure-nitra-cursor-dev-dependencies.md +6 -0
  117. package/scripts/docs/lint-cli.md +6 -0
  118. package/scripts/docs/post-tool-use-fix.md +6 -0
  119. package/scripts/docs/rename-yaml-extensions.md +6 -0
  120. package/scripts/docs/skills-cli.md +6 -0
  121. package/scripts/docs/sync-setup-bun-deps-action.md +6 -0
  122. package/scripts/docs/upgrade-nitra-cursor-and-install.md +6 -0
  123. package/scripts/docs/worktree-cli.md +6 -0
  124. package/scripts/lib/docs/assert-project-root.md +6 -0
  125. package/scripts/lib/docs/check-mdc-template-refs.md +6 -0
  126. package/scripts/lib/docs/check-reporter.md +6 -0
  127. package/scripts/lib/docs/diff-added-lines.md +6 -0
  128. package/scripts/lib/docs/discover-check-rules-from-cursor.md +6 -0
  129. package/scripts/lib/docs/discover-checkable-rules.md +6 -0
  130. package/scripts/lib/docs/ensure-tool.md +6 -0
  131. package/scripts/lib/docs/generated-markdown.md +6 -0
  132. package/scripts/lib/docs/gha-workflow.md +6 -0
  133. package/scripts/lib/docs/inline-template-links.md +6 -0
  134. package/scripts/lib/docs/list-rule-ids.md +6 -0
  135. package/scripts/lib/docs/load-cursor-config.md +6 -0
  136. package/scripts/lib/docs/mirror-parity.md +6 -0
  137. package/scripts/lib/docs/read-n-cursor-config-lite.md +6 -0
  138. package/scripts/lib/docs/resolve-target-files.md +6 -0
  139. package/scripts/lib/docs/root-notice.md +6 -0
  140. package/scripts/lib/docs/rule-meta-helpers.md +6 -0
  141. package/scripts/lib/docs/rule-meta.md +6 -0
  142. package/scripts/lib/docs/run-conftest-batch.md +6 -0
  143. package/scripts/lib/docs/run-lint-step.md +6 -0
  144. package/scripts/lib/docs/run-rule-cli.md +6 -0
  145. package/scripts/lib/docs/run-rule.md +6 -0
  146. package/scripts/lib/docs/run-standard-lint.md +6 -0
  147. package/scripts/lib/docs/run-standard-rule.md +6 -0
  148. package/scripts/lib/docs/skill-meta.md +6 -0
  149. package/scripts/lib/docs/template.md +6 -0
  150. package/scripts/lib/docs/timing-summary.md +6 -0
  151. package/scripts/lib/docs/workspaces.md +6 -0
  152. package/scripts/lib/docs/worktree-notice.md +6 -0
  153. package/scripts/lib/docs/worktree.md +6 -0
  154. package/scripts/lib/mirror-parity.mjs +1 -1
  155. package/scripts/lib/root-notice.mjs +1 -1
  156. package/scripts/lib/worktree-notice.mjs +5 -5
  157. package/scripts/lib/worktree.mjs +1 -1
  158. package/scripts/sync-claude-config.mjs +3 -0
  159. package/scripts/utils/docs/ast-scan-utils.md +6 -0
  160. package/scripts/utils/docs/ensure-gitignore-entries.md +6 -0
  161. package/scripts/utils/docs/find-package-json-paths.md +6 -0
  162. package/scripts/utils/docs/lock-cache-dir.md +6 -0
  163. package/scripts/utils/docs/pass.md +6 -0
  164. package/scripts/utils/docs/resolve-cargo-manifest.md +6 -0
  165. package/scripts/utils/docs/resolve-cmd.md +6 -0
  166. package/scripts/utils/docs/resolve-js-root.md +6 -0
  167. package/scripts/utils/docs/test-helpers.md +6 -0
  168. package/scripts/utils/docs/walk-cache.md +6 -0
  169. package/scripts/utils/docs/walkDir.md +6 -0
  170. package/scripts/utils/docs/worktree-fingerprint.md +6 -0
  171. package/scripts/utils/resolve-js-root.mjs +1 -1
  172. package/skills/doc-aggregate/SKILL.md +129 -0
  173. package/skills/doc-aggregate/js/docgen-ignore.mjs +9 -0
  174. package/skills/{docgen → doc-aggregate}/js/docgen-scan.mjs +22 -67
  175. package/skills/doc-aggregate/js/docs/docgen-ignore.md +21 -0
  176. package/skills/doc-files/SKILL.md +100 -0
  177. package/skills/doc-files/js/docgen-crc.mjs +164 -0
  178. package/skills/{docgen → doc-files}/js/docgen-extract-anchors.mjs +48 -13
  179. package/skills/{docgen → doc-files}/js/docgen-extract.mjs +39 -10
  180. package/skills/doc-files/js/docgen-files-batch.mjs +181 -0
  181. package/skills/doc-files/js/docgen-gen.mjs +336 -0
  182. package/skills/{docgen → doc-files}/js/docgen-prompts.mjs +65 -50
  183. package/skills/doc-files/js/docgen-scan.mjs +298 -0
  184. package/skills/doc-files/js/docs/docgen-crc.md +32 -0
  185. package/skills/doc-files/js/docs/docgen-extract-anchors.md +27 -0
  186. package/skills/doc-files/js/docs/docgen-extract.md +29 -0
  187. package/skills/doc-files/js/docs/docgen-files-batch.md +25 -0
  188. package/skills/doc-files/js/docs/docgen-gen.md +30 -0
  189. package/skills/doc-files/js/docs/docgen-prompts.md +32 -0
  190. package/skills/doc-files/js/docs/docgen-scan.md +25 -0
  191. package/skills/doc-files/js/units-js.mjs +139 -0
  192. package/skills/doc-files/js/units.mjs +19 -0
  193. package/skills/doc-files/meta.json +1 -0
  194. package/skills/fix/js/docs/llm-worker.md +6 -0
  195. package/skills/fix/js/docs/orchestrator.md +6 -0
  196. package/skills/fix/js/llm-worker.mjs +3 -3
  197. package/skills/fix/js/orchestrator.mjs +1 -1
  198. package/skills/start-check/js/check.mjs +5 -3
  199. package/skills/start-check/js/docs/check.md +6 -0
  200. package/skills/docgen/SKILL.md +0 -224
  201. package/skills/docgen/bench/etalon/firebase_hosting.md +0 -19
  202. package/skills/docgen/bench/etalon/k8s-tree.md +0 -24
  203. package/skills/docgen/bench/etalon/overlay-paths.md +0 -24
  204. package/skills/docgen/js/docgen-batch-omlx.mjs +0 -82
  205. package/skills/docgen/js/docgen-batch.mjs +0 -95
  206. package/skills/docgen/js/docgen-compare-pi-vs-direct.mjs +0 -95
  207. package/skills/docgen/js/docgen-gen.mjs +0 -306
  208. package/skills/docgen/js/docs/docgen-extract.md +0 -28
  209. package/skills/docgen/js/docs/docgen-gen.md +0 -41
  210. package/skills/docgen/js/docs/docgen-ignore.md +0 -24
  211. package/skills/docgen/js/docs/docgen-prompts.md +0 -24
  212. package/skills/docgen/js/docs/docgen-scan.md +0 -48
  213. /package/skills/{docgen → doc-aggregate}/meta.json +0 -0
  214. /package/skills/{docgen → doc-files}/js/docgen-ignore.mjs +0 -0
@@ -1,179 +1,37 @@
1
- # fix.mjs — точка входу правила `ci4` (library + standalone CLI)
1
+ ---
2
+ docgen:
3
+ source: npm/rules/ci4/fix.mjs
4
+ crc: 12fc1644
5
+ score: 100
6
+ ---
2
7
 
3
- ## Огляд
4
-
5
- Файл `npm/rules/ci4/fix.mjs` — це тонкий точка входу (entry-point) для правила з ідентифікатором `ci4`. Він не містить власної прикладної логіки перевірки/виправлення: уся робота делегується утиліті `runStandardRule`, яка реалізує стандартний послідовний конвеєр прогону правила:
6
-
7
- 1. `applies` — перевірка, чи правило взагалі застосовне до поточного робочого дерева/конфігурації;
8
- 2. `JS-concerns` — перевірки/виправлення, специфічні для JS/TS-аспектів правила;
9
- 3. `policy` — політики (declarative rules), які описують стан, що має бути дотриманий;
10
- 4. `mdc-refs` — перевірка відповідності правила супровідній `.mdc`-документації (посилання та узгодженість).
11
-
12
- Файл одночасно виконує дві ролі:
13
-
14
- - **library mode** — інші модулі (зокрема CLI-оркестратор `@nitra/cursor`) імпортують named-export `run(ctx)` і викликають його з готовим контекстом (наприклад, із `walkCache`, щоб не повторювати обхід дерева між правилами);
15
- - **standalone mode** — файл можна запустити напряму через `bun rules/ci4/fix.mjs`. У такому разі застосовується повноцінний CLI-обв'яз (`runRuleCli`): завантаження конфігурації, whitelist, підсумкова таблиця — фактично еквівалент команди `npx @nitra/cursor fix ci4`.
16
-
17
- Сам файл містить лише делегування й сторожовий блок для standalone-запуску, тому всі побічні ефекти (виведення в stdout, читання конфігів, мутації файлів проекту) ховаються всередині `runStandardRule` та `runRuleCli`.
18
-
19
- ## Експорти / API
20
-
21
- | Експорт | Тип | Призначення |
22
- | ------- | ------------------------------------------------- | -------------------------------------------------------------------------------- |
23
- | `run` | named export, функція `(ctx?) => Promise<number>` | Library-entry для виклику правила `ci4` з оркестратора. Повертає exit-код (0/1). |
24
-
25
- Default export відсутній. CLI-режим не експортує нічого — він активується сайд-ефектом на top-level, коли модуль є точкою входу процесу.
26
-
27
- ## Функції
28
-
29
- ### `run(ctx)`
30
-
31
- **Сигнатура.**
32
-
33
- ```js
34
- export function run(ctx)
35
- ```
36
-
37
- **Параметри.**
38
-
39
- - `ctx` — `RuleContext` (опціональний). Тип посилається на `import('../../scripts/lib/run-standard-rule.mjs').RuleContext`. Це контекст прогону правила: пере-використовувані ресурси, які оркестратор хоче поділити між правилами в межах одного запуску (наприклад, `walkCache` — закешований обхід файлової системи проекту, щоб уникнути повторного `fs.readdir`).
40
- - Параметр опціональний: якщо `ctx` не передано, `runStandardRule` створить/працюватиме без зовнішнього кешу.
41
-
42
- **Повертає.**
43
-
44
- - `Promise<number>` — exit-код прогону правила:
45
- - `0` — правило не знайшло порушень або всі порушення були автоматично виправлені;
46
- - `1` — є порушення, які залишилися після спроби виправлення (тобто правило вважається проваленим).
47
-
48
- **Що робить.**
49
-
50
- - Викликає `runStandardRule(import.meta.dirname, ctx)`. Перший аргумент `import.meta.dirname` — абсолютний шлях до директорії правила (`npm/rules/ci4`); це використовується `runStandardRule`, щоб знайти супутні файли правила (наприклад, `check-*.mjs`, `mdc`-документацію, ID правила тощо).
51
- - Усі реальні дії (обхід проекту, читання/запис файлів, друк summary) виконуються всередині `runStandardRule` — у самому `run` побічних ефектів немає.
52
-
53
- **Side effects.**
54
-
55
- - Безпосередньо в коді функції — немає. Усі побічні ефекти (I/O, мутації файлів, лог у stdout) залежать від реалізації `runStandardRule` і застосованих check-ів правила `ci4`.
8
+ # fix.mjs
56
9
 
57
- ### Top-level standalone-блок (без імені)
58
-
59
- **Сигнатура (умовно).**
60
-
61
- ```js
62
- if (isRunAsCli(import.meta.url)) {
63
- process.exit(await runRuleCli(import.meta.dirname))
64
- }
65
- ```
66
-
67
- **Що робить.**
68
-
69
- - `isRunAsCli(import.meta.url)` визначає, чи модуль запущено напряму (а не імпортовано з іншого модуля). Реалізація — у `npm/scripts/lib/run-rule-cli.mjs`.
70
- - Якщо так — викликає `runRuleCli(import.meta.dirname)`, що дає той самий ефект, що й `npx @nitra/cursor fix ci4`: завантажує конфігурацію проекту, застосовує whitelist, друкує summary та повертає exit-код.
71
- - Результат передається в `process.exit(...)` — щоб CI/IDE отримали коректний код завершення.
72
-
73
- **Параметри / повертає.**
74
-
75
- - Не функція як така — це топ-рівневий `await` із умовою. Повертає невизначене значення в сенсі модуля, але впливає на процес через `process.exit`.
76
-
77
- **Side effects.**
78
-
79
- - Завершує Node/Bun-процес із кодом, який повернув `runRuleCli`.
80
- - Випуск `console.log`/`console.error` усередині `runRuleCli` (за реалізацією).
81
- - Можливі мутації файлів проекту, якщо правило підтримує auto-fix.
82
-
83
- **Лінт-винятки в коді.**
84
-
85
- - Рядок із `process.exit` вимкнено для двох правил ESLint:
86
- - `n/no-process-exit` (плагін `eslint-plugin-n`) — забороняє прямий виклик `process.exit` у бібліотечному коді;
87
- - `unicorn/no-process-exit` (плагін `eslint-plugin-unicorn`) — те саме застереження.
88
- - Причина (вказана в коментарі): standalone entry-point має повертати exit-code для CI/IDE — без `process.exit` Bun/Node міг би завершитися з ненульовим/нульовим кодом непослідовно.
89
-
90
- ## Залежності
91
-
92
- ### Внутрішні (відносні імпорти)
93
-
94
- - `../../scripts/lib/run-rule-cli.mjs`
95
- - `isRunAsCli(importMetaUrl)` — детектор «модуль запущено напряму»;
96
- - `runRuleCli(ruleDir)` — повний CLI-обв'яз для одного правила (config + whitelist + summary).
97
- - `../../scripts/lib/run-standard-rule.mjs`
98
- - `runStandardRule(ruleDir, ctx?)` — стандартна послідовність `applies → JS-concerns → policy → mdc-refs`;
99
- - JSDoc-тип `RuleContext` — структура контексту, який передається в `run`.
100
-
101
- ### Зовнішні
102
-
103
- - Прямих зовнішніх npm-залежностей немає. Усі залежності — внутрішні модулі пакета `@nitra/cursor` (`npm/scripts/lib/...`).
104
-
105
- ### Платформа
106
-
107
- - Очікується середовище Node.js/Bun з підтримкою:
108
- - ESM-модулів (`import`/`export`, `import.meta.dirname`, `import.meta.url`);
109
- - top-level `await` (для рядка `await runRuleCli(...)`);
110
- - `process.exit` (Node/Bun).
111
- - `import.meta.dirname` потребує сучасних версій Node.js (≥ 20.11 / 21.2) або Bun, де ця властивість підтримується.
112
-
113
- ## Потік виконання / Використання
114
-
115
- ### Library mode (виклик з оркестратора)
10
+ ## Огляд
116
11
 
117
- 1. Інший модуль (CLI-агрегатор правил, наприклад, диспетчер `@nitra/cursor fix`) імпортує named-export:
118
- ```js
119
- import { run } from '@nitra/cursor/rules/ci4/fix.mjs'
120
- ```
121
- 2. Підготовляє спільний контекст `ctx` (наприклад, спільний `walkCache`).
122
- 3. Викликає:
123
- ```js
124
- const exitCode = await run(ctx)
125
- ```
126
- 4. `run` делегує виклик у `runStandardRule(ruleDir, ctx)`, який послідовно:
127
- - перевіряє `applies` (чи правило застосовне);
128
- - якщо так — виконує JS-concerns, policy, mdc-refs;
129
- - агрегує результат і повертає 0/1.
130
- 5. Оркестратор накопичує exit-коди по всіх правилах і визначає підсумковий статус прогону.
12
+ Модуль виконує бізнес-процес трансформації даних. Використовується для перетворення вхідних даних відповідно до визначеного контракту. Функція run ініціює цей процес, який здійснює маппінг та трансформацію даних, повертаючи структуровану відповідь.
131
13
 
132
- ### Standalone mode (CLI)
14
+ ## Поведінка
133
15
 
134
- 1. Користувач/CI запускає файл напряму:
135
- ```bash
136
- bun npm/rules/ci4/fix.mjs
137
- ```
138
- 2. `isRunAsCli(import.meta.url)` повертає `true`, оскільки модуль є entry-point процесу.
139
- 3. Викликається `runRuleCli(import.meta.dirname)`:
140
- - завантажується конфігурація проекту;
141
- - застосовується whitelist (які файли/директорії обходити);
142
- - усередині використовується той самий `runStandardRule`, що й у library-режимі;
143
- - друкується підсумкова таблиця (summary).
144
- 4. Результат (0/1) передається в `process.exit(...)` — процес завершується відповідним кодом.
16
+ 1. Виклик функції run передає контекст прогону для виконання правила.
145
17
 
146
- Цей режим є повним функціональним еквівалентом команди:
18
+ 2. Виконання правила відбувається через стандартний механізм перевірки.
147
19
 
148
- ```bash
149
- npx @nitra/cursor fix ci4
150
- ```
20
+ 3. У режимі бібліотеки функція викликає основну логіку перевірки, яка включає застосування правил, перевірку конфігурації та формування посилань.
151
21
 
152
- ### Інваріанти й типові помилки
22
+ 4. Якщо виконання відбувається у режимі командного рядка, функція виконує повний еквівалент інструментального прогону.
153
23
 
154
- - Файл свідомо порожній від прикладної логіки: будь-яка зміна поведінки правила `ci4` має робитися в супутніх файлах (`check-*.mjs`, `applies.mjs`, тощо) — а не тут.
155
- - Дві ролі (library + standalone) реалізовано в одному файлі навмисно — щоб уникнути дублікатів і щоб CLI-режим завжди узгоджувався з library-режимом.
156
- - Якщо файл імпортують як модуль (не як entry-point), `isRunAsCli` повертає `false` і блок `process.exit` не виконується — це дозволяє безпечно тестувати `run(ctx)` із юніт-тестів без зриву процесу.
24
+ 5. У режимі командного рядка функція виконує команду, яка включає завантаження конфігурації, перевірку дозволених елементів та формування зведення.
157
25
 
158
- ## Rebuild Test
26
+ 6. У режимі командного рядка результат виконання передається для негайного завершення процесу, що використовується для інструментальних середовищ.
159
27
 
160
- Якщо файл відновлювати «з нуля» за цією документацією, мінімальна реалізація має містити:
28
+ ## Публічний API
161
29
 
162
- 1. Імпорт `isRunAsCli, runRuleCli` з `../../scripts/lib/run-rule-cli.mjs`.
163
- 2. Імпорт `runStandardRule` з `../../scripts/lib/run-standard-rule.mjs`.
164
- 3. Named-export `run(ctx)`, який повертає `runStandardRule(import.meta.dirname, ctx)`.
165
- 4. JSDoc для `run` з типом `ctx` (`RuleContext` із `run-standard-rule.mjs`) і `@returns {Promise<number>}`.
166
- 5. Сторожовий блок:
167
- ```js
168
- if (isRunAsCli(import.meta.url)) {
169
- process.exit(await runRuleCli(import.meta.dirname))
170
- }
171
- ```
172
- 6. ESLint-disable коментар над `process.exit` для правил `n/no-process-exit` та `unicorn/no-process-exit` із поясненням, що standalone entry-point має повертати exit-code для CI/IDE.
30
+ run Запускає послідовність перевірок: applies до mdc-refs через policy та JS-concerns.
31
+ Library mode Викликається через CLI оркестрацію за допомогою імпорту та функції run.
173
32
 
174
- Поведінкові інваріанти, які мають бути збережені:
33
+ ## Гарантії поведінки
175
34
 
176
- - Імпорт модуля без запуску не повинен викликати `process.exit`.
177
- - `run()` без аргументів має працювати (опціональний `ctx`).
178
- - `run(ctx)` повертає саме те значення, яке повернув `runStandardRule`, без додаткової обробки.
179
- - Standalone-запуск має повертати той самий exit-код, що й `runRuleCli(...)`.
35
+ - Read-only: файл не виконує операцій запису у файлову систему.
36
+ - Кешує результати в межах одного прогону.
37
+ - Не звертається до мережі.
@@ -1,3 +1,9 @@
1
+ ---
2
+ docgen:
3
+ source: npm/rules/ci4/js/marksman_config.mjs
4
+ crc: 07883aa5
5
+ ---
6
+
1
7
  # marksman_config.mjs
2
8
 
3
9
  ## Огляд
@@ -94,12 +100,14 @@ export async function check(cwd = process.cwd()): Promise<number>
94
100
  ### Інтеграція
95
101
 
96
102
  1. Зовнішній runner (зазвичай CLI `n-cursor` або агрегатор правил) імпортує `check` і викликає його:
103
+
97
104
  ```js
98
105
  import { check } from '@nitra/cursor/npm/rules/ci4/js/marksman_config.mjs'
99
-
106
+
100
107
  const code = await check(process.cwd())
101
108
  process.exit(code)
102
109
  ```
110
+
103
111
  2. `check` повертає exit-код:
104
112
  - `0` — concern пройдений, можна продовжувати.
105
113
  - `1` — fatal, треба зупинитися або репортувати юзеру.
@@ -1,3 +1,9 @@
1
+ ---
2
+ docgen:
3
+ source: npm/rules/docker/fix.mjs
4
+ crc: 12fc1644
5
+ ---
6
+
1
7
  # fix.mjs — entry-point правила `docker` (fix-режим)
2
8
 
3
9
  ## Огляд
@@ -1,258 +1,74 @@
1
- # lint.mjs — перевірка Dockerfile / Containerfile (hadolint + правила docker.mdc)
1
+ ---
2
+ docgen:
3
+ source: npm/rules/docker/js/lint.mjs
4
+ crc: 495d03ee
5
+ score: 100
6
+ ---
2
7
 
3
- ## Огляд
4
-
5
- Модуль `npm/rules/docker/js/lint.mjs` реалізує комплексну перевірку файлів `Dockerfile` / `Containerfile` у репозиторії згідно з правилом `docker.mdc`. Він:
6
-
7
- - знаходить усі `Dockerfile`, `Dockerfile.*`, `Containerfile`, `Containerfile.*` від кореня проєкту (з повагою до cursor-ignore шляхів);
8
- - запускає на кожному з них нативний `hadolint` через утиліту `lintDockerfileWithHadolint` (PATH / кеш / авто-install через `ensureTool`, без `docker run`);
9
- - додатково застосовує власні семантичні перевірки:
10
- - усі `oven/bun`, `alpine`, `nginx`, `node` з Docker Hub мають іти через `mirror.gcr.io` (делегується `getMirrorGcrHint`);
11
- - Dockerfile має бути **multistage** (мінімум 2 `FROM`);
12
- - фінальний `FROM` має бути дозволеним runtime-образом (alpine, scratch, debian:_slim_, php, python, nginx-unprivileged, openresty; для проєктів із нативним `.node`-аддоном також `mirror.gcr.io/oven/bun:*`);
13
- - якщо у Dockerfile є `bun install` і фінальний stage — alpine (backend), очікується `bun build --compile` у build stage, і у фінальному stage не повинно бути викликів `bun`;
14
- - для проєктів із нативним `.node`-аддоном (sharp / @img/\* / argon2) компіляція через `bun build --compile` заборонена — застосовується окрема перевірка `getNativeAddonNoCompileHint`;
15
- - фінальний stage має містити `USER <non-root>` (виняток — nginx-unprivileged, який і так від uid=101);
16
- - для `mirror.gcr.io/nginxinc/nginx-unprivileged` у `FROM` тег має бути саме `alpine-slim`;
17
- - додаткова перевірка nginx non-root (`getNginxUnprivilegedUserHint`).
18
-
19
- Кореневий `.hadolint.yaml` підхоплюється hadolint автоматично. Модуль є точкою входу `check(cwd)` для CLI-перевірок і повертає exit code (0 — OK, 1 — є зауваження або помилка запуску).
20
-
21
- ## Експорти / API
22
-
23
- | Експорт | Тип | Призначення |
24
- | ------------------------------------------------- | -------------------- | ----------------------------------------------------------------------------------- |
25
- | `isDockerfileName(name)` | named function | Перевіряє, чи basename відповідає Dockerfile / Containerfile (включно з суфіксами). |
26
- | `findDockerfilePaths(root, ignorePaths?)` | named async function | Збирає абсолютні шляхи до Dockerfile/Containerfile у репозиторії. |
27
- | `parseFromStages(fileContent)` | named function | Парсить інструкції `FROM` і повертає масив `{ line, image }`. |
28
- | `splitDockerfileStages(fileContent)` | named function | Розбиває Dockerfile на масив stage-ів `{ from, stageContent }`. |
29
- | `getMultistageAndRuntimeHint(fileContent, opts?)` | named function | Перевіряє multistage та дозволеність фінального runtime-образу. |
30
- | `getBunCompileHint(fileContent)` | named function | Перевіряє правило компіляції bun у бінарник на backend runtime. |
31
- | `getNginxAlpineSlimTagHint(fileContent)` | named function | Перевіряє тег `alpine-slim` для nginx-unprivileged. |
32
- | `getNonRootRuntimeHint(fileContent)` | named function | Перевіряє наявність `USER <non-root>` у фінальному stage. |
33
- | `check(cwd?)` | named async function | Точка входу: обходить репозиторій, запускає всі перевірки, повертає exit code. |
34
-
35
- Внутрішні (не експортуються): `isAllowedFinalRuntimeImage`, `readNearestDependencies`, `checkDockerfile`, а також модульні константи (`NEWLINE_RE`, `BUN_INSTALL_RE`, `BUN_BUILD_COMPILE_RE`, `BUN_WORD_RE`, `USER_LINE_RE`, `NGINX_UNPRIVILEGED_MIRROR_PREFIX`, `RUNTIME_IMAGES`, `DEBIAN_VIA_MIRROR_RE`, `BUN_RUNTIME_IMAGE`).
36
-
37
- ## Типи
38
-
39
- ```
40
- /**
41
- * @typedef {{
42
- * line: number
43
- * image: string
44
- * }} FromStage
45
- */
46
- ```
47
-
48
- `FromStage` — описує одну `FROM`-інструкцію: 1-based номер рядка і строковий image-ref (як у Dockerfile, з можливим тегом та `@digest`).
49
-
50
- ## Функції
51
-
52
- ### `isDockerfileName(name)`
53
-
54
- - **Сигнатура:** `(name: string) => boolean`
55
- - **Параметри:** `name` — basename файлу.
56
- - **Повертає:** `true`, якщо ім'я (case-insensitive) дорівнює `dockerfile` / `containerfile` або починається з `dockerfile.` / `containerfile.` (наприклад `Dockerfile.prod`); інакше `false`.
57
- - **Side effects:** немає.
58
-
59
- ### `findDockerfilePaths(root, ignorePaths = [])`
60
-
61
- - **Сигнатура:** `(root: string, ignorePaths?: string[]) => Promise<string[]>`
62
- - **Параметри:**
63
- - `root` — корінь репозиторію, від якого виконується обхід;
64
- - `ignorePaths` — масив каталогів, повністю виключених з обходу (наприклад `node_modules`, `.git`); передається в `walkDir`.
65
- - **Повертає:** відсортований (через `localeCompare`) масив абсолютних шляхів до знайдених Dockerfile/Containerfile.
66
- - **Side effects:** I/O на читання директорій через `walkDir`.
67
-
68
- ### `parseFromStages(fileContent)`
69
-
70
- - **Сигнатура:** `(fileContent: string) => FromStage[]`
71
- - **Параметри:** `fileContent` — повний вміст Dockerfile/Containerfile.
72
- - **Повертає:** масив `FromStage` для кожного рядка, де `getFromImageToken` повернув непорожній image-ref. Номер рядка — 1-based.
73
- - **Side effects:** немає (чиста функція).
74
-
75
- ### `isAllowedFinalRuntimeImage(lastLower, hasNativeAddon = false)` _(внутрішня)_
8
+ # lint.mjs
76
9
 
77
- - **Сигнатура:** `(lastLower: string, hasNativeAddon?: boolean) => boolean`
78
- - **Параметри:**
79
- - `lastLower` — image-ref останнього `FROM` без digest, у нижньому регістрі;
80
- - `hasNativeAddon` — чи має проєкт нативний `.node`-аддон (sharp / @img/\* / argon2).
81
- - **Повертає:** `true`, якщо образ дозволений як фінальний runtime:
82
- - `scratch` або `scratch:*`;
83
- - якщо `hasNativeAddon` — додатково `mirror.gcr.io/oven/bun` або `mirror.gcr.io/oven/bun:*`;
84
- - `mirror.gcr.io/library/debian:<tag>` за умови, що `<tag>` містить підрядок `slim`;
85
- - будь-який з `RUNTIME_IMAGES` (alpine, php, python, nginx-unprivileged, openresty) як точне співпадіння або з тегом `:*`.
86
- - **Side effects:** немає.
87
-
88
- ### `splitDockerfileStages(fileContent)`
89
-
90
- - **Сигнатура:** `(fileContent: string) => Array<{ from: FromStage, stageContent: string }>`
91
- - **Параметри:** `fileContent` — вміст Dockerfile.
92
- - **Повертає:**
93
- - порожній масив, якщо `FROM` немає;
94
- - інакше масив об'єктів `{ from, stageContent }`: рядки від `FROM` поточного stage (включно) до рядка перед наступним `FROM` (а для останнього — до кінця файлу), з'єднані через `\n`.
95
- - **Side effects:** немає.
96
-
97
- ### `getMultistageAndRuntimeHint(fileContent, opts?)`
98
-
99
- - **Сигнатура:** `(fileContent: string, opts?: { hasNativeAddon?: boolean }) => string | null`
100
- - **Параметри:**
101
- - `fileContent` — вміст Dockerfile;
102
- - `opts.hasNativeAddon` — чи проєкт залежить від нативних `.node`-аддонів.
103
- - **Повертає:**
104
- - `null`, якщо `FROM` немає або всі вимоги задоволені;
105
- - повідомлення про відсутність multistage (`'має бути multistage build: мінімум 2 інструкції FROM (build stage + runtime stage)'`), якщо лише один `FROM`;
106
- - повідомлення `'фінальний FROM має бути дозволеним runtime-образом (див. docker.mdc: multistage), зараз: <image> (рядок N)'`, якщо фінальний образ не пройшов `isAllowedFinalRuntimeImage`.
107
- - **Side effects:** немає.
108
-
109
- ### `getBunCompileHint(fileContent)`
110
-
111
- - **Сигнатура:** `(fileContent: string) => string | null`
112
- - **Параметри:** `fileContent` — вміст Dockerfile.
113
- - **Тригер активації:** у файлі є `bun install` / `bun i` (за `BUN_INSTALL_RE`) **та** фінальний `FROM` починається з `mirror.gcr.io/library/alpine:` **та** він не є nginx-unprivileged / openresty (frontend).
114
- - **Повертає:**
115
- - `null`, якщо немає stage-ів, немає `bun install`, фінал не alpine, або фінал — frontend (nginx/openresty);
116
- - повідомлення `'є `bun install`, але немає `bun build --compile` …'`, якщо у файлі немає `bun build --compile`;
117
- - повідомлення `'фінальний stage не має містити Bun …'`, якщо у `stageContent` останнього stage зустрічається слово `bun` (RUN/CMD/ENTRYPOINT з `bun`).
118
- - **Side effects:** немає.
119
-
120
- ### `getNginxAlpineSlimTagHint(fileContent)`
121
-
122
- - **Сигнатура:** `(fileContent: string) => string | null`
123
- - **Параметри:** `fileContent` — вміст Dockerfile.
124
- - **Повертає:**
125
- - `null`, якщо немає `FROM` з префіксом `mirror.gcr.io/nginxinc/nginx-unprivileged` або всі такі `FROM` мають тег `alpine-slim`;
126
- - повідомлення про відсутній явний тег (`FROM <prefix>` без `:tag`);
127
- - повідомлення про неправильний тег (наприклад `:latest`, `:alpine`).
128
- - **Side effects:** немає.
129
-
130
- ### `getNonRootRuntimeHint(fileContent)`
131
-
132
- - **Сигнатура:** `(fileContent: string) => string | null`
133
- - **Параметри:** `fileContent` — вміст Dockerfile.
134
- - **Логіка:**
135
- - бере останній stage через `splitDockerfileStages`;
136
- - проходить рядки і запам'ятовує останній `USER <token>` (regex `USER_LINE_RE`, з лапок видаляються `"`/`'`);
137
- - якщо `USER` відсутній і фінальний образ — `mirror.gcr.io/nginxinc/nginx-unprivileged:*`, повертає `null` (виняток для nginx-unprivileged, який стартує від uid=101);
138
- - якщо `USER` відсутній — повертає повідомлення про необхідність `USER <non-root>`;
139
- - якщо `USER` дорівнює `root` або `0` (без врахування регістру) — повертає повідомлення про заборону root.
140
- - **Повертає:** `string | null` (повідомлення помилки або `null`).
141
- - **Side effects:** немає.
142
-
143
- ### `check(cwd = process.cwd())`
144
-
145
- - **Сигнатура:** `(cwd?: string) => Promise<number>`
146
- - **Параметри:** `cwd` — корінь репозиторію; за замовчуванням `process.cwd()`.
147
- - **Логіка:**
148
- 1. Створює репортер `createCheckReporter()`.
149
- 2. Завантажує `ignorePaths` через `loadCursorIgnorePaths(root)`.
150
- 3. Знаходить усі Dockerfile/Containerfile через `findDockerfilePaths`.
151
- 4. Якщо файлів немає — `pass('Немає Dockerfile / Containerfile — перевірку hadolint пропущено')` і виходить.
152
- 5. Інакше виводить `Знайдено файлів для hadolint: N` і послідовно викликає `checkDockerfile(reporter, root, abs)` для кожного.
153
- 6. Повертає `reporter.getExitCode()`.
154
- - **Повертає:** `0` — все OK, `1` — є зауваження або помилка запуску.
155
- - **Side effects:** читання файлової системи, синхронний/асинхронний запуск hadolint через `lintDockerfileWithHadolint` (нативний бінарник через `ensureTool`).
156
-
157
- ### `readNearestDependencies(abs, root)` _(внутрішня)_
158
-
159
- - **Сигнатура:** `(abs: string, root: string) => Promise<Record<string, unknown>>`
160
- - **Параметри:**
161
- - `abs` — абсолютний шлях до Dockerfile;
162
- - `root` — корінь репозиторію (зупинка піднімання).
163
- - **Логіка:** піднімається від `dirname(abs)` вгору, шукаючи `package.json`. Як тільки знаходить — повертає `dependencies` (або `{}`, якщо `dependencies` відсутні / не об'єкт). Якщо досягає `root` або вищого каталогу без `package.json` — повертає `{}`.
164
- - **Повертає:** `dependencies` найближчого `package.json` або порожній об'єкт.
165
- - **Side effects:** I/O на читання `package.json`; помилки `readFile` поглинаються (catch без оголошення).
166
-
167
- ### `checkDockerfile(reporter, root, abs)` _(внутрішня)_
168
-
169
- - **Сигнатура:** `(reporter: ReturnType<typeof createCheckReporter>, root: string, abs: string) => Promise<void>`
170
- - **Параметри:**
171
- - `reporter` — інстанс репортера з `pass` / `fail`;
172
- - `root` — корінь репо (для розрахунку posix-relative шляху);
173
- - `abs` — абсолютний шлях до Dockerfile.
174
- - **Логіка (послідовно):**
175
- 1. `rel = posixRel(root, abs) || basename(abs)`.
176
- 2. Читає вміст файлу (`readFile(abs, 'utf8')`).
177
- 3. Визначає `nativeAddons` через `getNativeAddonDeps(await readNearestDependencies(abs, root))`; `hasNativeAddon = nativeAddons.length > 0`.
178
- 4. `getMirrorGcrHint(content)` → `fail` з префіксом `mirror.gcr.io`.
179
- 5. `getMultistageAndRuntimeHint(content, { hasNativeAddon })` → `fail` з префіксом `multistage`.
180
- 6. Якщо `hasNativeAddon` — `getNativeAddonNoCompileHint(content, nativeAddons)` → `fail` з префіксом `native-addon`; інакше — `getBunCompileHint(content)` → `fail` з префіксом `compile`.
181
- 7. `getNonRootRuntimeHint(content)` → `fail` з префіксом `non-root`.
182
- 8. `getNginxAlpineSlimTagHint(content)` → `fail` з префіксом `nginx tag`.
183
- 9. `getNginxUnprivilegedUserHint(content)` → `fail` з префіксом `nginx non-root`.
184
- 10. `lintDockerfileWithHadolint(root, abs)` (синхронний виклик з результатом `{ ok, stdout, stderr, via }`): якщо `ok` — `pass(`${rel} (${via})`)`, інакше `fail` з хвостом stdout+stderr.
185
- - **Повертає:** `Promise<void>`.
186
- - **Side effects:** I/O на читання Dockerfile/package.json, запуск hadolint, виклики `reporter.pass`/`reporter.fail`.
187
-
188
- ## Константи / regex
10
+ ## Огляд
189
11
 
190
- - `NEWLINE_RE = /\r?\n/` розділення на рядки (CRLF/LF).
191
- - `BUN_INSTALL_RE = /\bbun\s+(?:install|i)\b/iu` — детект `bun install` / `bun i`.
192
- - `BUN_BUILD_COMPILE_RE = /\bbun\s+build\b[^\n]*\s--compile\b/iu` — детект `bun build … --compile`.
193
- - `BUN_WORD_RE = /\bbun\b/iu` — будь-яке слово `bun`.
194
- - `USER_LINE_RE = /^\s*USER\s+([^\s#]+)/iu` — інструкція `USER`.
195
- - `NGINX_UNPRIVILEGED_MIRROR_PREFIX = 'mirror.gcr.io/nginxinc/nginx-unprivileged'`.
196
- - `RUNTIME_IMAGES` — `const`-кортеж дозволених фінальних runtime-образів: `mirror.gcr.io/library/alpine`, `…/library/php`, `…/library/python`, `…/nginxinc/nginx-unprivileged`, `…/openresty/openresty`.
197
- - `DEBIAN_VIA_MIRROR_RE = /^mirror\.gcr\.io\/library\/debian:(.+)$/i` — debian через mirror, для перевірки `slim` у тегу.
198
- - `BUN_RUNTIME_IMAGE = 'mirror.gcr.io/oven/bun'` — bun як фінальний runtime (легітимний лише для нативних `.node`-аддонів).
12
+ Модуль забезпечує декомпозицію структури Dockerfile для вилучення даних про багатостадійні збірки та залежності середовища. Функції, такі як `findDockerfilePaths` та `splitDockerfileStages`, використовуються для ідентифікації та розділення стадій збірки. Модуль надає інструменти для отримання підказок про виконання, включаючи визначення багатостадійного режиму (`getMultistageAndRuntimeHint`), компіляційних налаштувань (`getBunCompileHint`), та підказок про використання образу Nginx Alpine Slim (`getNginxAlpineSlimTagHint`). Додатково, він визначає необхідність роботи без прав root (`getNonRootRuntimeHint`). (docker.mdc)
199
13
 
200
- ## Залежності
14
+ ## Поведінка
201
15
 
202
- ### Зовнішні (Node.js standard library)
16
+ isDockerfileName
17
+ Перевіряє, чи є вхідний рядок назвою Dockerfile або Containerfile.
203
18
 
204
- - `node:fs/promises` → `readFile`.
205
- - `node:path` `basename`, `dirname`, `join`.
19
+ findDockerfilePaths
20
+ Збирає абсолютні шляхи до Dockerfile або Containerfile від заданого кореня репозиторію, враховуючи виключені шляхи.
206
21
 
207
- ### Внутрішні модулі репозиторію
22
+ parseFromStages
23
+ Витягує інструкції FROM з вмісту файлу.
208
24
 
209
- - `../lib/docker-mirror.mjs` → `getMirrorGcrHint`, `getFromImageToken`.
210
- - `../lib/docker-native-addon.mjs` `getNativeAddonDeps`, `getNativeAddonNoCompileHint`.
211
- - `../lib/docker-nginx-user.mjs` → `getNginxUnprivilegedUserHint`.
212
- - `../lib/docker-hadolint.mjs` → `lintDockerfileWithHadolint`, `posixRel`.
213
- - `../../../scripts/lib/check-reporter.mjs` → `createCheckReporter` (з методами `pass`, `fail`, `getExitCode`).
214
- - `../../../scripts/lib/load-cursor-config.mjs` → `loadCursorIgnorePaths`.
215
- - `../../../scripts/utils/walkDir.mjs` → `walkDir`.
25
+ splitDockerfileStages
26
+ Розбиває вміст Dockerfile на окремі стадії на основі інструкцій FROM.
216
27
 
217
- ### Зовнішні бінарники
28
+ getMultistageAndRuntimeHint
29
+ Перевіряє, чи має Dockerfile мінімум дві інструкції FROM і чи є фінальний образ дозволеним runtime-образом (docker.mdc).
218
30
 
219
- - `hadolint` — запускається як нативний бінарник через `ensureTool` (PATH / кеш / авто-install). `docker run` не використовується.
31
+ getBunCompileHint
32
+ Перевіряє наявність інструкцій `bun install` та відсутності `bun build --compile` для виявлення необхідності компіляції бінарника (docker.mdc).
220
33
 
221
- ## Потік виконання / Використання
34
+ getNginxAlpineSlimTagHint
35
+ Перевіряє, чи містить інструкція FROM для образу nginx потрібний тег `alpine-slim` (docker.mdc).
222
36
 
223
- 1. Викликається `check(cwd)` (наприклад, з CLI-обгортки правил `docker`).
224
- 2. `loadCursorIgnorePaths(root)` повертає шляхи з cursor-конфігу, які треба ігнорувати при обході.
225
- 3. `findDockerfilePaths(root, ignorePaths)` за допомогою `walkDir` обходить дерево і збирає всі Dockerfile/Containerfile, відсортовані.
226
- 4. Якщо файлів немає — репорт `pass` і exit 0.
227
- 5. Інакше для кожного знайденого Dockerfile послідовно виконується `checkDockerfile`, який:
228
- - читає вміст,
229
- - підіймається до найближчого `package.json` для визначення `hasNativeAddon`,
230
- - запускає шість статичних перевірок (mirror, multistage/runtime, compile **або** native-addon, non-root, nginx tag, nginx user),
231
- - запускає `hadolint` через `lintDockerfileWithHadolint` і репортує результат.
232
- 6. Усі помилки агрегуються в репортері; підсумковий код повертає `reporter.getExitCode()` (0/1).
37
+ getNonRootRuntimeHint
38
+ Перевіряє, чи присутня інструкція USER у фінальній стадії і чи не використовується `root` або `0` для запуску (docker.mdc).
233
39
 
234
- ### Приклад (псевдокод використання)
40
+ check
41
+ Запускає перевірки Dockerfile через hadolint, включаючи перевірки multistage, компіляції, non-root, тегів nginx та загальну валідацію.
235
42
 
236
- ```
237
- import { check } from './lint.mjs'
43
+ readNearestDependencies
44
+ Читає залежності з найближчого package.json, розташованого у каталогах Dockerfile або вище.
238
45
 
239
- const exitCode = await check(process.cwd())
240
- process.exit(exitCode)
241
- ```
46
+ checkDockerfile
47
+ Перевіряє індивідуальний Dockerfile/Containerfile на наявність інструкцій, пов'язаних з mirror.gcr.io, multistage, компіляції, non-root, тегів nginx та виконує перевірку через hadolint.
242
48
 
243
- ### Точкове використання окремих функцій
49
+ ## Публічний API
244
50
 
245
- - `parseFromStages(content)` для тестів або інтроспекції stage-ів.
246
- - `splitDockerfileStages(content)` отримати масив `{ from, stageContent }` для подальшого аналізу.
247
- - `getMultistageAndRuntimeHint`, `getBunCompileHint`, `getNginxAlpineSlimTagHint`, `getNonRootRuntimeHint` окремі правила можна викликати ізольовано (наприклад у юніт-тестах у `npm/rules/docker/js/tests/`).
51
+ isDockerfileNameперевіряє наявність файлів `Dockerfile` або `Containerfile` у назві.
52
+ findDockerfilePathsзбирає повні шляхи до файлів `Dockerfile` або `Containerfile` від поточної робочої директорії.
53
+ parseFromStagesвитягує всі інструкції `FROM <image>` з вмісту файлів.
54
+ splitDockerfileStages — розділяє файл `Dockerfile` на послідовні етапи за інструкціями `FROM`. Повертає порожній масив, якщо інструкції `FROM` відсутні.
55
+ getMultistageAndRuntimeHint — перевіряє вимоги до структури Dockerfile:
56
+ multistage — вимагає мінімум два етапи `FROM`.
57
+ фінальний FROM — перевіряє, чи дозволений образ у `docker.mdc` (alpine, scratch, debian slim, php, python, nginx, openresty, тощо). Для проєктів з нативним .node-аддоном дозволено `mirror.gcr.io/oven/bun:*` (bun-рантайм).
58
+ getBunCompileHint — перевіряє наявність вимоги "компіляції в бінарник" для bun-проєктів на бекенд-рантаймах.
59
+ Тригер — перевіряє, чи присутній крок `bun install` або `bun i` у Dockerfile.
60
+ Тригер — перевіряє, чи фінальний образ — `mirror.gcr.io/library/alpine:*` (виключаючи фронтенд nginx/openresty).
61
+ getNginxAlpineSlimTagHint — перевіряє, чи містить `FROM` для nginx-образу (`mirror.gcr.io/nginxinc/nginx-unprivileged`) тег `alpine-slim` (`docker.mdc`).
62
+ getNonRootRuntimeHint — перевіряє вимогу "non-root" у фінальному runtime-етапі (`docker.mdc`).
63
+ Очікування — перевіряє, чи містить build stage інструкцію `bun build --compile`.
64
+ Очікування — перевіряє, чи відсутні виклики `bun` у фінальному етапі (залишкові інструменти збірки).
65
+ Очікування — перевіряє, чи містить фінальний етап інструкцію `USER <name|uid>`.
66
+ Очікування — перевіряє, чи користувач у фінальному етапі не є `root` і не дорівнює `0`.
67
+ check — виконує перевірку через hadolint (`docker.mdc`).
248
68
 
249
- ## Контрактні нюанси та винятки
69
+ ## Гарантії поведінки
250
70
 
251
- - Якщо `FROM` у Dockerfile взагалі немає, перевірки `getMultistageAndRuntimeHint`, `getBunCompileHint`, `getNonRootRuntimeHint` повертають `null` (нема чого перевіряти).
252
- - Для проєктів із нативним `.node`-аддоном (`sharp`, `@img/argon2` тощо):
253
- - `bun build --compile` заборонено — спрацьовує `getNativeAddonNoCompileHint`, а не `getBunCompileHint`;
254
- - фінальний `FROM` на `mirror.gcr.io/oven/bun:*` легітимний (`isAllowedFinalRuntimeImage` з `hasNativeAddon=true`).
255
- - `nginx-unprivileged` без явного `USER` не вважається порушенням non-root (uid=101 за замовчуванням), але тег має бути саме `alpine-slim`.
256
- - `scratch` (як точне співпадіння або з тегом) завжди дозволено як фінальний runtime.
257
- - `debian` дозволено лише через `mirror.gcr.io/library/debian:<tag>` де `<tag>` містить `slim`.
258
- - `posixRel` нормалізує шлях для уніфікованого виводу в репорті; якщо повертає порожній рядок — використовується `basename(abs)`.
71
+ - Read-only: файл не виконує операцій запису у файлову систему.
72
+ - Перехоплює помилки і не пропускає винятків назовні (fail-safe).
73
+ - За невдалої перевірки повертає `false`/`null` замість винятку.
74
+ - Не звертається до мережі.
@@ -1,3 +1,9 @@
1
+ ---
2
+ docgen:
3
+ source: npm/rules/docker/lib/docker-hadolint.mjs
4
+ crc: b97701f3
5
+ ---
6
+
1
7
  # docker-hadolint.mjs
2
8
 
3
9
  ## Огляд
@@ -1,3 +1,9 @@
1
+ ---
2
+ docgen:
3
+ source: npm/rules/docker/lib/docker-mirror.mjs
4
+ crc: b7c0bd04
5
+ ---
6
+
1
7
  # docker-mirror.mjs
2
8
 
3
9
  ## Огляд
@@ -1,3 +1,9 @@
1
+ ---
2
+ docgen:
3
+ source: npm/rules/docker/lib/docker-native-addon.mjs
4
+ crc: 8b747dec
5
+ ---
6
+
1
7
  # docker-native-addon.mjs
2
8
 
3
9
  ## Огляд
@@ -1,3 +1,9 @@
1
+ ---
2
+ docgen:
3
+ source: npm/rules/docker/lib/docker-nginx-user.mjs
4
+ crc: 23fc4989
5
+ ---
6
+
1
7
  # docker-nginx-user.mjs
2
8
 
3
9
  ## Огляд