@nitra/cursor 3.26.0 → 3.28.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 (128) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/bin/n-cursor.js +29 -9
  3. package/package.json +1 -1
  4. package/rules/abie/js/applies.mjs +1 -5
  5. package/rules/abie/js/env_dns.mjs +1 -9
  6. package/rules/abie/js/firebase_hosting.mjs +1 -5
  7. package/rules/abie/js/hc_pairing.mjs +1 -8
  8. package/rules/abie/js/ua_http_route.mjs +1 -10
  9. package/rules/abie/js/ua_node_selector.mjs +1 -8
  10. package/rules/adr/js/hooks.mjs +1 -20
  11. package/rules/bun/js/layout.mjs +1 -19
  12. package/rules/capacitor/js/platforms.mjs +1 -23
  13. package/rules/changelog/js/consistency.mjs +1 -29
  14. package/rules/ci4/js/marksman_config.mjs +1 -19
  15. package/rules/docker/js/lint.mjs +1 -34
  16. package/rules/ga/docs/fix.md +16 -149
  17. package/rules/ga/js/docs/lint.md +12 -93
  18. package/rules/ga/js/docs/workflows.md +28 -213
  19. package/rules/ga/js/workflows.mjs +1 -16
  20. package/rules/ga/lint/docs/lint.md +24 -206
  21. package/rules/graphql/js/tooling.mjs +1 -9
  22. package/rules/hasura/js/internal_urls.mjs +1 -24
  23. package/rules/image-avif/js/avif_generation.mjs +1 -27
  24. package/rules/image-compress/js/package_setup.mjs +1 -18
  25. package/rules/js-bun-db/js/safety.mjs +1 -31
  26. package/rules/js-bun-redis/js/imports.mjs +1 -12
  27. package/rules/js-lint/js/docs/lint-findings.md +30 -0
  28. package/rules/js-lint/js/lint-findings.mjs +1 -7
  29. package/rules/js-lint/js/lint.mjs +1 -10
  30. package/rules/js-lint/js/tooling.mjs +1 -13
  31. package/rules/js-lint/js/utils_imports.mjs +1 -18
  32. package/rules/js-lint-ci/js/lint.mjs +1 -6
  33. package/rules/js-mssql/js/deps.mjs +1 -10
  34. package/rules/js-run/js/runtime.mjs +1 -37
  35. package/rules/js-run/lib/docs/temporal-scan.md +25 -0
  36. package/rules/k8s/js/manifests.mjs +1 -137
  37. package/rules/nginx-default-tpl/js/template.mjs +1 -18
  38. package/rules/npm-module/js/docs/header_doc_pointer.md +25 -0
  39. package/rules/npm-module/js/header_doc_pointer.mjs +82 -0
  40. package/rules/npm-module/js/package_structure.mjs +1 -28
  41. package/rules/npm-module/js/rule_meta.mjs +1 -10
  42. package/rules/npm-module/js/skill_meta.mjs +1 -13
  43. package/rules/php/js/tooling.mjs +1 -11
  44. package/rules/python/js/applies.mjs +1 -8
  45. package/rules/python/js/tooling.mjs +1 -21
  46. package/rules/rego/js/applies.mjs +1 -11
  47. package/rules/rust/js/applies.mjs +1 -7
  48. package/rules/security/js/sample_secret.mjs +1 -28
  49. package/rules/security/js/trufflehog.mjs +1 -8
  50. package/rules/style-lint/js/lint.mjs +1 -5
  51. package/rules/style-lint/js/tooling.mjs +1 -19
  52. package/rules/tauri/js/cargo_mutants_config.mjs +1 -20
  53. package/rules/tauri/js/tooling.mjs +1 -21
  54. package/rules/test/js/cargo_mutants_config.mjs +1 -12
  55. package/rules/test/js/location.mjs +1 -9
  56. package/rules/test/js/no-process-chdir.mjs +1 -21
  57. package/rules/test/js/no-relative-fs-path.mjs +1 -23
  58. package/rules/test/js/stryker_config.mjs +4 -25
  59. package/rules/test/js/vitest-config-pool-forks.mjs +1 -17
  60. package/rules/text/js/forbidden-prettier.mjs +1 -10
  61. package/rules/text/js/formatting.mjs +1 -31
  62. package/rules/vue/js/packages.mjs +1 -24
  63. package/scripts/docs/coverage-fix-extract.md +32 -0
  64. package/scripts/docs/lint-cli.md +25 -0
  65. package/scripts/docs/post-tool-use-fix.md +27 -0
  66. package/scripts/docs/rename-yaml-extensions.md +36 -0
  67. package/scripts/docs/skills-cli.md +35 -0
  68. package/scripts/docs/sync-claude-config.md +52 -0
  69. package/scripts/docs/sync-setup-bun-deps-action.md +26 -0
  70. package/scripts/docs/upgrade-nitra-cursor-and-install.md +29 -0
  71. package/scripts/docs/worktree-cli.md +46 -0
  72. package/scripts/lib/docs/assert-project-root.md +28 -0
  73. package/scripts/lib/docs/diff-added-lines.md +34 -0
  74. package/scripts/lib/docs/read-n-cursor-config-lite.md +28 -0
  75. package/scripts/lib/docs/resolve-target-files.md +34 -0
  76. package/scripts/lib/docs/root-notice.md +28 -0
  77. package/scripts/lib/docs/rule-meta-helpers.md +34 -0
  78. package/scripts/lib/docs/rule-meta.md +34 -0
  79. package/scripts/lib/docs/rule-predicates.md +30 -0
  80. package/scripts/lib/docs/run-conftest-batch.md +26 -0
  81. package/scripts/lib/docs/run-lint-step.md +25 -0
  82. package/scripts/lib/docs/run-rule-cli.md +27 -0
  83. package/scripts/lib/docs/run-rule.md +32 -0
  84. package/scripts/lib/docs/run-standard-lint.md +22 -0
  85. package/scripts/lib/docs/run-standard-rule.md +24 -0
  86. package/scripts/lib/docs/skill-meta.md +31 -0
  87. package/scripts/lib/docs/sync-gitignore-worktree.md +31 -0
  88. package/scripts/lib/docs/template.md +40 -0
  89. package/scripts/lib/docs/timing-summary.md +24 -0
  90. package/scripts/lib/docs/workspaces.md +30 -0
  91. package/scripts/lib/docs/worktree-notice.md +27 -0
  92. package/scripts/lib/docs/worktree.md +38 -0
  93. package/scripts/utils/docs/ast-scan-utils.md +50 -0
  94. package/scripts/utils/docs/ensure-gitignore-entries.md +28 -0
  95. package/scripts/utils/docs/find-package-json-paths.md +26 -0
  96. package/scripts/utils/docs/lock-cache-dir.md +25 -0
  97. package/scripts/utils/docs/pass.md +25 -0
  98. package/scripts/utils/docs/resolve-cargo-manifest.md +23 -0
  99. package/scripts/utils/docs/resolve-cmd.md +29 -0
  100. package/scripts/utils/docs/resolve-js-root.md +25 -0
  101. package/scripts/utils/docs/test-helpers.md +36 -0
  102. package/scripts/utils/docs/walk-cache.md +27 -0
  103. package/scripts/utils/docs/walkDir.md +32 -0
  104. package/scripts/utils/docs/with-lock.md +25 -0
  105. package/scripts/utils/docs/worktree-fingerprint.md +27 -0
  106. package/skills/docgen/js/docgen-batch.mjs +95 -0
  107. package/skills/docgen/js/docgen-extract.mjs +33 -18
  108. package/skills/docgen/js/docgen-gen.mjs +258 -30
  109. package/skills/docgen/js/docgen-ignore.mjs +4 -7
  110. package/skills/docgen/js/docgen-prompts.mjs +40 -23
  111. package/skills/docgen/js/docgen-scan.mjs +1 -8
  112. package/skills/docgen/js/docs/docgen-extract.md +28 -0
  113. package/skills/docgen/js/docs/docgen-gen.md +41 -0
  114. package/skills/docgen/js/docs/docgen-ignore.md +24 -0
  115. package/skills/docgen/js/docs/docgen-prompts.md +24 -0
  116. package/skills/docgen/js/docs/docgen-scan.md +48 -0
  117. package/skills/fix/SKILL.md +5 -31
  118. package/skills/fix/js/docs/llm-worker.md +27 -0
  119. package/skills/fix/js/docs/orchestrator.md +32 -0
  120. package/skills/fix/js/docs/t0.md +29 -0
  121. package/skills/fix/js/llm-worker.mjs +216 -0
  122. package/skills/fix/js/orchestrator.mjs +119 -0
  123. package/skills/fix/js/t0.mjs +213 -0
  124. package/skills/fix/meta.json +1 -1
  125. package/skills/start-check/js/check.mjs +1 -16
  126. package/skills/start-check/js/docs/check.md +34 -0
  127. package/skills/taze/js/diff.mjs +1 -15
  128. package/skills/taze/js/docs/diff.md +33 -0
@@ -1,209 +1,27 @@
1
- # `npm/rules/ga/lint/lint.mjs`
1
+ # lint.mjs
2
2
 
3
3
  ## Огляд
4
4
 
5
- Модуль `lint.mjs` — це **CLI-обгортка над канонічним `lint-ga`** (правило `ga.mdc`), яка виконує комплексну перевірку GitHub Actions workflow-файлів проєкту. Модуль не є самостійним перевіряльником: він агрегує кілька стадій external-tools і делегує JS/Rego-частину перевірок в `rules/ga/fix.mjs::check()`.
6
-
7
- Ключові зони відповідальності:
8
-
9
- 1. **Авто-встановлення обов'язкових бінарників** `shellcheck` і `conftest` через `ensureTool` (підбирається менеджер пакетів per-platform: `brew`/`scoop`/GitHub Release).
10
- 2. **Preflight для `uv`** м'яка перевірка, що `uv` отже `uvx`) є в `PATH`; інакше друкується hint з командами встановлення й функція повертає `1` без авто-install.
11
- 3. **Послідовний запуск трьох стадій перевірки** workflow-ів:
12
- - `bunx github-actionlint` синтаксис/семантика GH Actions, включно з вбудованим `shellcheck` у `run:` блоках (звідси preflight на `shellcheck`).
13
- - `uvx zizmor --offline --collect=workflows .` second-stage security-аудит workflow на ризики (через `uv`/`uvx`).
14
- - `rules/ga/fix.mjs::check()` Rego-полісі (батч `conftest` для `npm/policy/ga/`) **плюс** JS cross-file перевірки правил `ga.mdc`. Це та сама перевірка, що й `npx @nitra/cursor check ga`, тож `lint-ga` є суперсетом цієї підкоманди.
15
- 4. **Серіалізація запуску** через `runStandardLint(import.meta.dirname, steps)` згідно з каноном патерну `lint-*` (див. `.cursor/rules/scripts.mdc`, секція «Серіалізація важких CLI-команд») — без прямого `withLock`.
16
-
17
- Plan B-патерн (rego-authoritative): сама Rego-полісі `npm/policy/ga/` запускає `rules/ga/fix.mjs::check()` як перший крок — `lint.mjs` про це не знає. Раніше `lint.mjs` сам спавнив `conftest` per-workflow для `ga.<name>` і `ga.workflow_common` (PoC); тепер уся логіка централізована в `rules/ga/fix.mjs`, тому одне джерело істини без дублювання між `lint-ga` і `npx @nitra/cursor check ga`.
18
-
19
- Чому preflight на `shellcheck` обов'язковий: без нього `bunx github-actionlint` **мовчки** пропускає shell-перевірки у `run:` блоках; локально `bun lint-ga` лишається зеленим, а CI на `ubuntu-latest` (де `shellcheck` передвстановлений) падає. `ensureTool('shellcheck')` усуває цю різницю.
20
-
21
- Чому `uv` — окремо й лише як hint: бінарник `uv` не входить у реєстр `ensureTool` для авто-install у цьому проєкті, тому модуль обмежується інформативною підказкою з командами встановлення (brew / curl / pip), щоб користувач не отримав неінформативну помилку від `uvx zizmor`.
22
-
23
- Модуль експортує одну іменовану стрілкову функцію `runLintGaCli`, яку імпортує `bin/n-cursor.js` як обробник підкоманди `lint-ga`.
24
-
25
- ## Експорти / API
26
-
27
- | Символ | Тип | Експорт | Опис |
28
- | -------------- | ------------------------------- | ---------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
29
- | `runLintGaCli` | `() => Promise<number>` (arrow) | `export const` (named) | Точка входу CLI-команди `lint-ga`. Обгортає `runLintGaSteps` у `runStandardLint(import.meta.dirname, ...)` — серіалізація + стандартні timing/exit-code/log конвенції. |
30
-
31
- Жодних інших експортів модуль не надає: усі допоміжні функції (`resolvePreflightBin`, `printPreflightMissingMessage`, `preflight`, `runLintGaSteps`) і константа `UV_PREFLIGHT` — внутрішні.
32
-
33
- JSDoc-typedef `PreflightDep` описує форму внутрішніх preflight-конфігів і не експортується.
34
-
35
- ## Функції
36
-
37
- ### `resolvePreflightBin(dep)`
38
-
39
- ```
40
- function resolvePreflightBin(dep: PreflightDep): string | null
41
- ```
42
-
43
- - **Параметри:**
44
- - `dep: PreflightDep` — опис preflight-залежності з полями `bin`, `winBins`, `explanation`, `install`, `successMsg`.
45
- - **Повертає:** `string | null` — абсолютний шлях до бінарника або `null`, якщо нічого не знайдено в `PATH`.
46
- - **Поведінка:**
47
- - Якщо `platform === 'win32'` (з `node:process`), спершу ітерує `dep.winBins` (наприклад, `['uv.exe']`) і повертає перший резолвлений шлях.
48
- - Якщо жоден `winBins` не знайдено або платформа не Windows — фолбек на `resolveCmd(dep.bin)`.
49
- - **Side effects:** немає (читання `PATH` через `resolveCmd` — pure-resolve).
50
-
51
- ### `printPreflightMissingMessage(dep)`
52
-
53
- ```
54
- function printPreflightMissingMessage(dep: PreflightDep): void
55
- ```
56
-
57
- - **Параметри:** `dep: PreflightDep`.
58
- - **Повертає:** `void`.
59
- - **Поведінка:** друкує у `stderr` блок із кількох рядків:
60
- 1. `❌ <bin> не знайдено в PATH.` (червоний хрестик у вигляді емодзі).
61
- 2. Пояснення з `dep.explanation` (одинарний відступ на 3 пробіли).
62
- 3. Заголовок `Встанови:` і список команд із `dep.install` з відступом на 5 пробілів.
63
- 4. Фінальний рядок-вказівка: `Деталі: ga.mdc → секція про lint-ga.`
64
- - **Side effects:** запис у `process.stderr` через `console.error`. Жодних винятків не кидає.
65
-
66
- ### `preflight(dep)`
67
-
68
- ```
69
- function preflight(dep: PreflightDep): boolean
70
- ```
71
-
72
- - **Параметри:** `dep: PreflightDep`.
73
- - **Повертає:** `boolean` — `true`, якщо бінарник знайдено в `PATH`; `false`, якщо ні.
74
- - **Поведінка:**
75
- - Викликає `resolvePreflightBin(dep)`.
76
- - На pass: друкує `dep.successMsg` через `console.log` і повертає `true`.
77
- - На fail: викликає `printPreflightMissingMessage(dep)` і повертає `false`.
78
- - **Side effects:** запис у `stdout` (success) або `stderr` (fail) через `console.log`/`console.error`.
79
-
80
- ### `runLintGaSteps()`
81
-
82
- ```
83
- async function runLintGaSteps(): Promise<number>
84
- ```
85
-
86
- - **Параметри:** немає.
87
- - **Повертає:** `Promise<number>` — `0`, якщо всі кроки успішні; інакше — exit-code першого кроку, що впав.
88
- - **Поведінка (послідовно):**
89
- 1. `ensureTool('shellcheck')` — авто-install або hard-fail (кидає виняток, який підхоплює `runStandardLint` і конвертує в `exit 1`).
90
- 2. `ensureTool('conftest')` — те саме.
91
- 3. `preflight(UV_PREFLIGHT)` — якщо `uv` не знайдено, повертає `1` без падіння (hint-only).
92
- 4. `runLintStep('actionlint', 'bunx', ['github-actionlint'])` → якщо код ≠ 0, повертає його.
93
- 5. `runLintStep('zizmor', 'uvx', ['zizmor', '--offline', '--collect=workflows', '.'])` → якщо код ≠ 0, повертає його.
94
- 6. Друкує заголовок `▶ check-ga (rego-полісі npm/policy/ga/ + JS cross-file перевірки)` і повертає `await checkGa()` (з `../js/workflows.mjs`).
95
- - **Side effects:**
96
- - Можлива інсталяція пакетів через `ensureTool` (мутує систему: brew/scoop/завантаження бінарників).
97
- - Спавн процесів `bunx`, `uvx` через `runLintStep`.
98
- - Виклик `conftest` (батчем) і JS-перевірки всередині `checkGa()`.
99
- - Запис у `stdout`/`stderr`.
100
-
101
- ### `runLintGaCli` (експортовано)
102
-
103
- ```
104
- export const runLintGaCli: () => Promise<number>
105
- ```
106
-
107
- - **Параметри:** немає.
108
- - **Повертає:** `Promise<number>` — результат `runStandardLint(...)`, тобто фінальний exit-code лінт-команди.
109
- - **Поведінка:** обгортає `runLintGaSteps` у `runStandardLint(import.meta.dirname, runLintGaSteps)`. `import.meta.dirname` визначає каталог `npm/rules/ga/lint/`, що використовується для лок-файлу серіалізації та для службових логів.
110
- - **Side effects:** успадковуються від `runStandardLint` (lock-файл / cleanup) і `runLintGaSteps`.
111
-
112
- ## Внутрішні дані
113
-
114
- ### `UV_PREFLIGHT`
115
-
116
- ```
117
- const UV_PREFLIGHT: PreflightDep
118
- ```
119
-
120
- Конфігурація preflight для `uv`:
121
-
122
- - `bin: 'uv'`
123
- - `winBins: ['uv.exe']`
124
- - `explanation`: двохрядкове пояснення про те, що без `uv`/`uvx` не запуститься `uvx zizmor` (second-stage аудит workflow на ризики GitHub Actions).
125
- - `install`:
126
- - `'macOS: brew install uv'`
127
- - `'Universal: curl -LsSf https://astral.sh/uv/install.sh | sh'`
128
- - `'pip: pip install uv'`
129
- - `successMsg: '✅ uv знайдено в PATH — uvx zizmor запуститься'`
130
-
131
- ### `PreflightDep` (JSDoc typedef)
132
-
133
- Структура опису однієї preflight-залежності:
134
-
135
- | Поле | Тип | Опис |
136
- | ------------- | ---------- | ---------------------------------------------------------------------------------------------- |
137
- | `bin` | `string` | Базове ім'я виконуваного файлу (на Windows додається `.exe` за потреби — через `winBins`). |
138
- | `winBins` | `string[]` | Альтернативні імена на Windows (наприклад, `shellcheck.exe`); якщо порожньо — фолбек на `bin`. |
139
- | `explanation` | `string` | 1–2 рядки, що пояснюють наслідки відсутності бінарника. |
140
- | `install` | `string[]` | Список рядків з командами встановлення (друкуються «як є», з відступом). |
141
- | `successMsg` | `string` | Повідомлення, яке друкується на pass-шлях preflight-у. |
142
-
143
- ## Залежності
144
-
145
- ### Зовнішні (Node.js core)
146
-
147
- - `node:process` — імпортується `platform` (рядок типу `'darwin' | 'linux' | 'win32' | ...`) для гілки Windows у `resolvePreflightBin`.
148
-
149
- ### Внутрішні (проєктні)
150
-
151
- - `../js/workflows.mjs` — імпорт `check as checkGa`. Виконує Rego-полісі (батч `conftest` для `npm/policy/ga/`) і JS cross-file перевірки правил `ga.mdc`. Це фінальний крок `runLintGaSteps`.
152
- - `../../../scripts/utils/resolve-cmd.mjs` — `resolveCmd(name): string | null`. Pure-resolve бінарника у `PATH` (без спавну).
153
- - `../../../scripts/lib/run-lint-step.mjs` — `runLintStep(label, cmd, args): number`. Стандартизований обгортковий спавн одного кроку lint-у з консистентним логом і exit-code-семантикою.
154
- - `../../../scripts/lib/run-standard-lint.mjs` — `runStandardLint(dirname, fn): Promise<number>`. Канонічна серіалізація lint-команди (lock-файл, тривалість, sentry-style cleanup). Згідно з `.cursor/rules/scripts.mdc` (секція «Серіалізація важких CLI-команд»), цей хелпер заміняє прямий `withLock` у lint-обгортках.
155
- - `../../../scripts/lib/ensure-tool.mjs` — `ensureTool(name): void`. Перевіряє наявність бінарника в `PATH` і автоматично встановлює його через відповідний менеджер пакетів per-platform (brew/scoop/GitHub Release). Кидає виняток на нездатність встановити.
156
-
157
- ### Зовнішні CLI-інструменти (запускаються в рантаймі)
158
-
159
- - `shellcheck` — авто-install через `ensureTool`. Потрібен для shell-перевірок у `run:` блоках, які виконує `actionlint`.
160
- - `conftest` — авто-install через `ensureTool`. Використовується **всередині** `checkGa()` для виконання Rego-полісі з `npm/policy/ga/`.
161
- - `uv` / `uvx` — hint-only preflight. Потрібен для запуску `uvx zizmor`.
162
- - `bunx` / `github-actionlint` — виконується через `runLintStep('actionlint', 'bunx', ['github-actionlint'])`.
163
- - `uvx` / `zizmor` — виконується через `runLintStep('zizmor', 'uvx', ['zizmor', '--offline', '--collect=workflows', '.'])`.
164
-
165
- ## Потік виконання / Використання
166
-
167
- ### Інтеграція в CLI
168
-
169
- Модуль експортує `runLintGaCli`, яку імпортує `bin/n-cursor.js` як обробник підкоманди:
170
-
171
- ```
172
- npx @nitra/cursor lint-ga
173
- # або
174
- bun lint-ga
175
- ```
176
-
177
- ### Сценарій типового запуску (happy path)
178
-
179
- 1. `runLintGaCli()` → викликає `runStandardLint(import.meta.dirname, runLintGaSteps)` — отримується lock на `npm/rules/ga/lint/`, починається timing.
180
- 2. Усередині `runLintGaSteps`:
181
- - `ensureTool('shellcheck')` — якщо нема, авто-встановлення (brew/scoop/release).
182
- - `ensureTool('conftest')` — те саме.
183
- - `preflight(UV_PREFLIGHT)` — друкує `✅ uv знайдено в PATH — uvx zizmor запуститься`.
184
- - `runLintStep('actionlint', 'bunx', ['github-actionlint'])` — exit `0`.
185
- - `runLintStep('zizmor', 'uvx', ['zizmor', '--offline', '--collect=workflows', '.'])` — exit `0`.
186
- - Лог `▶ check-ga (rego-полісі npm/policy/ga/ + JS cross-file перевірки)`.
187
- - `await checkGa()` — повертає `0`.
188
- 3. `runStandardLint` логує загальну тривалість, знімає lock і повертає `0`.
189
-
190
- ### Сценарії з falure
191
-
192
- - `shellcheck` або `conftest` не встановлено й `ensureTool` не зміг встановити — виняток пробивається крізь `runLintGaSteps`, `runStandardLint` ловить його та конвертує у `exit 1`.
193
- - `uv` відсутній — `preflight(UV_PREFLIGHT)` друкує hint, `runLintGaSteps` повертає `1`, наступні кроки не виконуються.
194
- - `actionlint` повертає не-нульовий код — `runLintGaSteps` повертає цей код, `zizmor` і `checkGa()` не запускаються.
195
- - `zizmor` повертає не-нульовий код — те саме: одразу повертається його exit-code.
196
- - `checkGa()` повертає не-нульовий код — він і є фінальним результатом `runLintGaCli`.
197
-
198
- ### Контракт «суперсет `check ga`»
199
-
200
- Оскільки фінальний крок `runLintGaSteps` — `checkGa()` (та сама `check`-функція з `../js/workflows.mjs`, що використовується підкомандою `npx @nitra/cursor check ga`), `lint-ga` є суперсетом цієї перевірки: він додає `actionlint` (синтаксис) і `zizmor` (security-аудит) перед `check`. Це усуває потребу запускати `check ga` окремо в pipeline-ах, що вже виконують `lint-ga`.
201
-
202
- ### Канон патерну `lint-*`
203
-
204
- Файл сповідує канон патерну `lint-*` із `.cursor/rules/scripts.mdc` (секція «Серіалізація важких CLI-команд»):
205
-
206
- - Серіалізація — через `runStandardLint`, **не** через прямий `withLock`.
207
- - Кожна стадія — через `runLintStep` (узгоджений лог-формат, semantic exit-codes).
208
- - Експортована функція має назву `run<Name>Cli` (тут — `runLintGaCli`).
209
- - Фінальна делегація бізнес-частини — у відповідний `rules/<name>/fix.mjs::check()`, щоб бути одним джерелом істини з `npx @nitra/cursor check <name>`.
5
+ Файл надає CLI-обгортку для інструменту `lint-ga`, який автоматично встановлює необхідні інструменти, такі як `shellcheck` та `conftest`, для перевірки коду. Він послідовно виконує перевірку коду за допомогою Rego та JavaScript, забезпечуючи узгодженість з правилами `ga.mdc`. Цей файл служить централізованим джерелом для виконання та налаштування процесу linting, що спрощує інтеграцію в CI/CD.
6
+
7
+ ## Поведінка
8
+
9
+ 1. **Підготовка середовища:** Перевіряє наявність необхідних інструментів: `shellcheck` та `conftest`. Якщо їх немає, автоматично встановлює їх, щоб забезпечити коректну роботу.
10
+ 2. **Перевірка залежностей:** Перевіряє наявність `uv`. Якщо `uv` відсутній, надає інструкції щодо його встановлення, щоб забезпечити виконання наступного етапу.
11
+ 3. **Запуск попередньої перевірки:** Виконує попередню перевірку за допомогою `github-actionlint`, що дозволяє виявити проблеми на ранніх етапах.
12
+ 4. **Виконання аналізу коду:** Запускає `uvx zizmor` для поглибленого аналізу коду, включаючи перевірку на відповідність стандартам та виявлення потенційних проблем.
13
+ 5. **Перевірка Rego-полісів:** Запускає Rego-полісі з `npm/policy/ga/` для забезпечення відповідності коду політикам.
14
+ 6. **Перевірка правил:** Виконує перевірку правил `ga.mdc` як для JS-коду, так і для Rego-полісів, забезпечуючи загальну відповідність стандартам.
15
+ 7. **Звіт про результати:** Формує звіт про результати перевірки, що включає інформацію про виявлені проблеми та їх серйозність.
16
+ 8. **Повернення статусу:** Повертає код завершення, що вказує на успішне виконання або наявність проблем, які потребують уваги.
17
+
18
+ ## Гарантії поведінки
19
+
20
+ - `ensureTool` встановлює `shellcheck` та `conftest` згідно з обраним методом встановлення (brew, scoop, GitHub Release).
21
+ - Якщо `uv` не встановлено, `uvx zizmor` завершується з помилкою.
22
+ - `bunx github-actionlint` пропускає shell-перевірки в `run:` блоках, якщо `shellcheck` не вказаний у PATH.
23
+ - `runLintGaCli` повертає `false` або `null` при помилках, не викликаючи виняток.
24
+ - Не використовується кешування.
25
+ - `uvx zizmor` вимагає наявності `uv`.
26
+ - Логіка встановлення та запуску перевірок централізована у `rules/ga/fix.mjs`.
27
+ - `runLintGaCli` використовується як підкоманда `lint-ga`.
@@ -1,12 +1,4 @@
1
- /**
2
- * Перевіряє правило graphql.mdc: наявність **`.graphqlrc.yml`** і рекомендації
3
- * **`graphql.vscode-graphql`**, якщо у дереві є **`gql\`…\``**.
4
- *
5
- * Обхід репозиторію — **`walkDir`** від **`process.cwd()`** (пропуски як у інших check). Кандидати — **`.vue`** та **`.js`/`.ts`/`.jsx`/`.tsx`** тощо; пропуск **`.d.ts`**, **auto-imports.d.ts** тощо — **`shouldSkipFileForGqlScan`**.
6
- *
7
- * Виявлення **`gql`** — **oxc-parser** після витягування `<script>` з SFC (**`graphql-gql-scan.mjs`**). Якщо збігів немає — перевірка завершується успішно без вимог до конфігів.
8
- * @param {string} cwd корінь репозиторію
9
- */
1
+ /** @see ./docs/tooling.md */
10
2
  import { existsSync } from 'node:fs'
11
3
  import { readFile } from 'node:fs/promises'
12
4
  import { join, relative } from 'node:path'
@@ -1,27 +1,4 @@
1
- /**
2
- * Перевіряє правило hasura.mdc для проєктів **nitra** і **abie**: значення
3
- * `HASURA_GRAPHQL_ENDPOINT` у `*.env` має бути **внутрішнім** кластерним URL,
4
- * а не публічним доменом.
5
- *
6
- * Запускається лише якщо в кореневому `package.json` поле `repository`
7
- * вказує на `https://github.com/nitra/...` або `https://github.com/abinbevefes/...`
8
- * (інші репозиторії пропускаються без помилок — як у abie-перевірках).
9
- *
10
- * Очікуваний формат URL — кластерний DNS-суфікс `<cluster>.internal`:
11
- * - GKE / GCP: `http://<service>.<namespace>.svc.<cluster>.internal:<port>`
12
- * приклад: `http://contract-h-hl.ua-contract.svc.abie-ua.internal:8080`
13
- *
14
- * Сегменти беруться з `hasura/k8s/base/svc-hl.yaml` (`metadata.name` —
15
- * headless, має закінчуватись на `-h-hl`; див. `hasura.svc_hl` / k8s.svc_hl_yaml) і
16
- * `hasura/k8s/base/namespace.yaml`
17
- * (`metadata.name` — namespace). Якщо ці YAML є в репозиторії, у URL додатково
18
- * звіряються конкретні `<service>` і `<namespace>` з ними.
19
- *
20
- * Скануються всі файли `*.env` (наприклад `dev.env`, `production.env`); файл
21
- * `.env` без імені — виключення з правила (локальний файл розробника), його
22
- * не перевіряємо. Пропускаються `node_modules`, `.git`, `dist`, `coverage`,
23
- * `.turbo`, `.next` (як у `walkDir`).
24
- */
1
+ /** @see ./docs/internal_urls.md */
25
2
  import { existsSync } from 'node:fs'
26
3
  import { readFile } from 'node:fs/promises'
27
4
  import { basename, join, relative } from 'node:path'
@@ -1,30 +1,4 @@
1
- /**
2
- * Перевіряє відповідність репозиторію правилу `image-avif.mdc`: AVIF-генерацію та
3
- * ув'язування `.avif`-двійників з посиланнями у `.vue`/`.html`.
4
- *
5
- * Дії під час `check image-avif`:
6
- * 1. **Pre-scan**: знайти в `.vue`/`.html` хоча б одне raster-посилання, яке потенційно
7
- * можна переписати на AVIF-двійник (через `import x from '...png'` або
8
- * `<img src="...png" />`). Пакети з opt-out `disable-avif: true` пропускаються.
9
- * Якщо жодного raster-посилання не знайдено → exit 0 одразу (`npx --avif` не запускаємо,
10
- * rewrite/cleanup-пасс теж пропускаємо — нічого не змінилось би).
11
- * 2. `npx \@nitra/minify-image --src=. --write --avif` — генерує AVIF-двійники.
12
- * 3. У кожному workspace-пакеті переписує raster-посилання у `.vue`/`.html` на `.avif`
13
- * (де AVIF-двійник реально існує на диску). Pakety з `"\@nitra/minify-image": {
14
- * "disable-avif": true }` у `package.json` пропускаються.
15
- * 4. Прибирає AVIF-сироти — `<name>.<ext>.avif`, на які не лишилось жодного посилання
16
- * у `.vue`/`.html` репозиторію, видаляються (умова правила: «AVIF лишається лише
17
- * там, де заміна вдалася»).
18
- *
19
- * Якщо raster-посилання у `.vue`/`.html` не вдалось переписати (наприклад, оригіналу
20
- * нема на диску → `.avif` теж не згенерувався) — фейл на конкретний файл.
21
- *
22
- * Правило самостійне від `image-compress`: AVIF можна вмикати лише в адмінках (де AVIF
23
- * підтримується сучасними браузерами) і не вмикати в публічних сайтах. Перевірка скрипта
24
- * `lint-image` (заборона `--avif` у ньому) залишається у `image-compress` — тут вона не
25
- * дублюється.
26
- * @param {string} cwd корінь репозиторію
27
- */
1
+ /** @see ./docs/avif_generation.md */
28
2
  import { existsSync } from 'node:fs'
29
3
  import { readFile, unlink, writeFile } from 'node:fs/promises'
30
4
  import { join, relative } from 'node:path'
@@ -1,21 +1,4 @@
1
- /**
2
- * Перевіряє вимоги правила `image-compress.mdc` для оптимізації raster/SVG через
3
- * `@nitra/minify-image` ≥ 3.2.0 (локально).
4
- *
5
- * **Що тут лишилося** (FS / cross-file):
6
- * - наявність `package.json` у корені;
7
- * - `.n-minify-image.tsv` (committed source of truth з sha1/originalSize/size) НЕ
8
- * в `.gitignore` — він має бути в git;
9
- * - застарілий `.minify-image-cache.tsv` (з версій < 3.2) видалений з кореня та
10
- * з `.gitignore`.
11
- *
12
- * **Що покрила Rego** (`npx \@nitra/cursor fix`,
13
- * `npm/rules/image-compress/policy/package_json/`):
14
- * - `scripts.lint-image` викликає `npx \@nitra/minify-image --src=. --write`
15
- * без `--avif` (AVIF — окреме правило `image-avif`);
16
- * - агрегований `lint` (якщо є) містить `bun run lint-image`;
17
- * - `@nitra/minify-image` НЕ у `dependencies` / `devDependencies` (через `npx`).
18
- */
1
+ /** @see ./docs/package_setup.md */
19
2
  import { existsSync } from 'node:fs'
20
3
  import { readFile } from 'node:fs/promises'
21
4
  import { join } from 'node:path'
@@ -1,34 +1,4 @@
1
- /**
2
- * Перевіряє правило js-bun-db.mdc.
3
- *
4
- * 1) У жодному `package.json` (включно з workspace-пакетами) у `dependencies` не повинно
5
- * бути `pg-format` чи `mysql2` — їх треба замінити на Bun native SQL
6
- * (`import { sql, SQL } from 'bun'`, https://bun.com/docs/runtime/sql). `pg-format` —
7
- * ручне форматування SQL через escape; tagged template Bun SQL параметризує значення
8
- * нативно і не лишає простору для injection. Перевірка цих двох — у Rego-полісі
9
- * `npm/policy/js_bun_db/package_json/`.
10
- *
11
- * 2) Для `pg` діє виключення: Bun SQL поки не реалізує LISTEN/NOTIFY, тож якщо у
12
- * проекті знайдено реальне використання `LISTEN ...` / `NOTIFY ...` / `UNLISTEN ...`
13
- * або listener'а `.on('notification', ...)`, dependency `pg` дозволено. Інакше
14
- * `pg` лишається забороненим — fail з підказкою про виключення. Додатково — per-file:
15
- * кожен файл з `import ... from 'pg'` повинен сам містити LISTEN/NOTIFY-патерн;
16
- * звичайні SELECT/INSERT/UPDATE через `pg` (replace на Bun SQL!) не дозволені.
17
- *
18
- * 3) Якщо в коді використовується Bun SQL (імпорт `sql`/`SQL` з `'bun'`), додатково
19
- * перевіряє небезпечні патерни:
20
- * - `new SQL(...)` всередині функції (пул має бути singleton на рівні модуля).
21
- * - Будь-який `<obj>.unsafe(...)` без маркера-коментаря `// allow-unsafe: <reason>`
22
- * на тому ж рядку або рядком вище. `sql.unsafe` за замовчуванням заборонено;
23
- * допустимий лише для підстановки назви таблиці/колонки чи dynamic SQL/DDL,
24
- * коли значення контролюється кодом (не user input) — в інших випадках
25
- * переробляємо на tagged template `sql\`...\${value}...\``.
26
- * - pg-leftover виклики `<obj>.connect(...)` / `<obj>.end(...)` у файлах, що
27
- * імпортують Bun SQL: пулом керує Bun, життєвий цикл вручну не потрібен.
28
- * Opt-out — маркер `// allow-pg-leftover: <reason>`.
29
- * - Динамічні SQL-списки через `.join(',')` у `IN (...)` / `VALUES (...)`
30
- * (треба `sql([...])`).
31
- */
1
+ /** @see ./docs/safety.md */
32
2
  import { existsSync } from 'node:fs'
33
3
  import { readFile } from 'node:fs/promises'
34
4
  import { join, relative } from 'node:path'
@@ -1,15 +1,4 @@
1
- /**
2
- * Перевіряє правило `js-bun-redis.mdc`.
3
- *
4
- * Заборонено в JS/TS-джерелах будь-який `import` / `require` / динамічний `import()` пакетів
5
- * `ioredis`, `node-redis`, `redis` (та підпакетів `@redis/*`, підшляхів `ioredis/...` /
6
- * `redis/...`). Замість них треба використовувати Bun native Redis:
7
- * `import { redis } from 'bun'` (<https://bun.com/docs/runtime/redis>).
8
- *
9
- * Перевірку `dependencies` (заборона `ioredis` / `node-redis` / `redis` / `@redis/*` у будь-якому
10
- * `package.json`) винесено в Rego-полісі `npm/policy/js_bun_redis/package_json/`; її запускає
11
- * `npx \@nitra/cursor check`. Тут лишився AST-скан коду через `oxc-parser`.
12
- */
1
+ /** @see ./docs/imports.md */
13
2
  import { existsSync } from 'node:fs'
14
3
  import { readFile } from 'node:fs/promises'
15
4
  import { join, relative } from 'node:path'
@@ -0,0 +1,30 @@
1
+ # lint-findings.mjs
2
+
3
+ ## Огляд
4
+
5
+ Цей файл обробляє результати аналізу коду, отримані з інструментів oXlint та eslint, для визначення, чи є знайдені проблеми нові (в diff) чи існують у файлі з самого початку. Він класифікує ці результати, надаючи інформацію про файл та рядок, де проблема виявлена, що допомагає у відстеженні та вирішенні помилок. Це частина системи беклогу #6, яка автоматизує процес класифікації lint-findings.
6
+
7
+ ## Поведінка
8
+
9
+ parseOxlint: аналізує JSON-вихід `oxlint --format=json` та повертає список findings з інформацією про файл, рядок, правило та повідомлення.
10
+ parseEslint: аналізує JSON-вихід `eslint --format=json` та повертає список findings з інформацією про файл, рядок, правило та повідомлення.
11
+ classifyFindings: класифікує findings як introduced або pre-existing на основі доданих рядків, використовуючи Map.
12
+ renderFindings: генерує текстовий звіт з розділенням findings на introduced та pre-existing, використовуючи формат `🆕 introduced` та `🗄 pre-existing`.
13
+
14
+ ## Публічний API
15
+
16
+ - parseOxlint — Перетворює JSON з результатів інструменту Oxlint на внутрішній об'єкт.
17
+ - parseEslint — Перетворює JSON з результатів інструменту ESLint на внутрішній об'єкт.
18
+ - classifyFindings — Розподіляє знайдені проблеми на нові (introduced) та існуючі (pre-existing).
19
+ - renderFindings — Створює звіт, об'єднуючи нові та існуючі проблеми.
20
+
21
+ ## Гарантії поведінки
22
+
23
+ - Функція `parseOxlint` повертає JSON-об'єкт, що містить список діагностик, або `null` у разі помилки парсингу.
24
+ - Функція `parseEslint` повертає масив об'єктів, що містять повідомлення про помилки, або `null` у разі помилки парсингу.
25
+ - Функція `classifyFindings` повертає масив об'єктів, що представляють класифіковані результати, або `null` у разі помилки класифікації.
26
+ - Функція `renderFindings` повертає рядок, що містить представлення результатів, або `null` у разі помилки рендерингу.
27
+ - У разі невдачі будь-якої з функцій, повертається `false`.
28
+ - Функції не кидають винятків.
29
+ - Шляхи файлів, що передаються вхідним функціям, є абсолютними.
30
+ - Результати функцій не кешуються.
@@ -1,10 +1,4 @@
1
- /**
2
- * Нормалізація й класифікація lint-findings (oxlint + eslint) на introduced
3
- * (рядок у diff від HEAD) vs pre-existing (борг файлу) — беклог #6, варіант A.
4
- *
5
- * Формати: oxlint `--format=json` → `{ diagnostics:[{ filename, code, labels:[{span:{line}}] }] }`;
6
- * eslint `--format=json` → `[{ filePath, messages:[{ ruleId, line, message }] }]`. Шляхи абсолютні.
7
- */
1
+ /** @see ./docs/lint-findings.md */
8
2
  import { isAbsolute, relative } from 'node:path'
9
3
 
10
4
  import { isIntroducedLine } from '../../../scripts/lib/diff-added-lines.mjs'
@@ -1,13 +1,4 @@
1
- /**
2
- * Quick-крок lint правила js-lint: oxlint + eslint (з автофіксом).
3
- *
4
- * Викликається lint-оркестратором (`n-cursor lint` / `lint-ci`):
5
- * - `files` = масив змінених файлів (quick) → лінтимо лише js-подібні з них і
6
- * КЛАСИФІКУЄМО лишені findings на introduced (рядок у diff від HEAD) vs
7
- * pre-existing (борг файлу) — беклог #6, варіант A (видимість; блокування без змін);
8
- * - `files` = undefined (ci) → лінтимо весь проєкт (стрімінг, без класифікації).
9
- * Крос-файлові jscpd/knip — окреме правило js-lint-ci (фаза ci).
10
- */
1
+ /** @see ./docs/lint.md */
11
2
  import { spawnSync } from 'node:child_process'
12
3
 
13
4
  import { addedLinesByFile } from '../../../scripts/lib/diff-added-lines.mjs'
@@ -1,16 +1,4 @@
1
- /**
2
- * Перевіряє лінт JavaScript за правилом js-lint.mdc.
3
- *
4
- * Flat ESLint з getConfig і ignore для auto-imports,
5
- * `.oxlintrc.json` має збігатися з каноном oxlint у пакеті (`npm/rules/js-lint/js/data/tooling/oxlint-canonical.json`):
6
- * plugins, jsPlugins, categories, усі правила з канону (додаткові записи в `rules` дозволені), settings, env,
7
- * globals, ignorePatterns. Також перевіряє workspace `package.json` на `type: "module"`
8
- * і `engines`, workflow-дубль у `lint.yml`, `knip.json` autofill і застарілі `.eslintrc*`.
9
- *
10
- * Per-document вимоги (`lint-js`, `@nitra/eslint-config`, root `engines`, `.jscpd.json`,
11
- * `.vscode/extensions.json`, `lint-js.yml`) — у policy-пакетах `js_lint.*`.
12
- * @param {string} cwd корінь репозиторію
13
- */
1
+ /** @see ./docs/tooling.md */
14
2
  import { existsSync } from 'node:fs'
15
3
  import { copyFile, readFile } from 'node:fs/promises'
16
4
  import { dirname, join } from 'node:path'
@@ -1,21 +1,4 @@
1
- /**
2
- * Перевіряє, що файли всередині будь-якого `utils/` каталогу не мають імпортів за межі
3
- * самого каталогу (relative-import з `..`). За правилом `js-lint.mdc` каталог `utils/` — це
4
- * generic helpers без бізнес-логіки і без залежностей від домену; якщо файлу потрібен
5
- * сусідній модуль, конфіг проєкту чи cross-rule helper — він має жити в `lib/`, а не в `utils/`.
6
- *
7
- * Перевіряються лише не-тестові `.mjs|.mts|.cjs|.cts|.js|.ts|.jsx|.tsx` під будь-яким
8
- * `utils/`-каталогом у monorepo-воркспейсах. Файли всередині `utils/tests/` (тести)
9
- * і будь-які `__fixtures__/` ігноруються — тести легально імпортують свій модуль через `../X`.
10
- *
11
- * Дозволені імпорти:
12
- * - `./X`, `./sub/X` — same-dir чи глибше всередині самої `utils/`
13
- * - bare-package (`oxc-parser`, `@scope/pkg`) — npm-залежність
14
- * - `node:fs`, `fs` тощо — Node-builtin
15
- *
16
- * Заборонено:
17
- * - будь-який `..`-шлях (`../X`, `../../X`) — це порушення granular `utils/`-кордону
18
- */
1
+ /** @see ./docs/utils_imports.md */
19
2
  import { readdir, readFile } from 'node:fs/promises'
20
3
  import { join, relative, sep } from 'node:path'
21
4
 
@@ -1,9 +1,4 @@
1
- /**
2
- * Ci-крок: jscpd (детектор клонів) + knip (невикористані експорти).
3
- *
4
- * Крос-файлові аналізатори — працюють лише по всьому репо, тож `files` ігнорується
5
- * (викликається лише у `lint-ci` з undefined). Per-file режиму ці інструменти не мають.
6
- */
1
+ /** @see ./docs/lint.md */
7
2
  import { spawnSync } from 'node:child_process'
8
3
 
9
4
  /**
@@ -1,13 +1,4 @@
1
- /**
2
- * Перевіряє правило js-mssql.mdc.
3
- *
4
- * Якщо в будь-якому `package.json` у репозиторії (включно з workspace-пакетами) в секції `dependencies`
5
- * присутній пакет `mssql`, його версія має бути не менше 12.5.0.
6
- *
7
- * Додатково, якщо `mssql` використовується в репозиторії, перевіряє що підключення
8
- * не створюється “на кожен запит”: `new sql.ConnectionPool(...)` не має знаходитись
9
- * всередині функцій. Пул має бути singleton (на рівні модуля) і повторно використовуватись.
10
- */
1
+ /** @see ./docs/deps.md */
11
2
  import { existsSync } from 'node:fs'
12
3
  import { readFile } from 'node:fs/promises'
13
4
  import { join, relative } from 'node:path'
@@ -1,40 +1,4 @@
1
- /**
2
- * Для кожного workspace-пакета перевіряє правило js-run.mdc.
3
- *
4
- * Покрито:
5
- * - заборона `@nitra/bunyan` / `bunyan` як у залежностях `package.json`, так і в коді
6
- * (`import` / `require` / динамічний `import()`); імпорти сканує AST через `oxc-parser`
7
- * (див. `utils/bunyan-imports.mjs`);
8
- * - наявність `OTEL_RESOURCE_ATTRIBUTES` зі значеннями `service.name=` та `service.namespace=`
9
- * у `k8s/base/configmap.yaml`, якщо такий файл існує (відповідність імені ConfigMap імені
10
- * Deployment перевіряється в `rules/k8s/fix.mjs`);
11
- * - «Внутрішні аліаси» (`#conn/*`): імпорти `bun#SQL`, будь-який `mssql`, `@nitra/graphql-request#GraphQLClient`
12
- * дозволені лише у каталозі conn (за замовчуванням `src/conn/`; за наявності
13
- * `package.json#imports['#conn/*']` — у його цільовому каталозі); поза ним — порушення
14
- * (див. `utils/conn-imports-scan.mjs`);
15
- * - «Нейминг та експорти у `#conn/`»: всередині conn-каталогу basename файла має відповідати
16
- * канону `ql-<id>` / `(pg|mysql|mssql)-(read|write)[-<id>]`; `export default` заборонений; має бути
17
- * іменований експорт з імʼям, що дорівнює camelCase від basename файла (`pg-write-contract.js`
18
- * → `export const pgWriteContract`); `index.*` як reexport-барель пропускаємо
19
- * (див. `utils/conn-file-rules.mjs`);
20
- * - «process.env / CheckEnv»: пряме `process.env.X` має бути замінено на `env` —
21
- * з `@nitra/check-env` (для обов'язкових змінних, із `checkEnv([...])`) або з
22
- * `node:process` (для опційних). Коли `env` імпортовано з `@nitra/check-env`,
23
- * кожен `env.X` має бути закритий літеральним викликом `checkEnv(['X', ...])`
24
- * у тому ж файлі або коментарем `// \@nitra/cursor ignore-next-line checkEnv`
25
- * на попередньому рядку (див. `utils/check-env-scan.mjs`);
26
- * - «Паузи через setTimeout»: `new Promise(resolve => setTimeout(resolve, ms))` (з/без `await`)
27
- * треба замінити на `await setTimeout(ms)` з `node:timers/promises`
28
- * (див. `utils/promise-settimeout-scan.mjs`);
29
- * - «Temporal у Bun runtime»: identifier `Temporal` заборонений, бо поточний Bun runtime
30
- * не має глобального Temporal API (див. `utils/temporal-scan.mjs`);
31
- * - «jsconfig.json»: у backend-пакеті з каталогом `src/` у корені має бути `jsconfig.json`,
32
- * вміст якого збігається з каноном js-run.mdc (NodeNext і include на дерево `src`).
33
- *
34
- * Per-document валідація `package.json` (bunyan, `node` у `scripts`) делегована rego-пакету
35
- * `js_run.package_json` у `npm/rules/js-run/policy/package_json/`; JS — cross-file (AST, FS).
36
- * @param {string} cwd корінь репозиторію
37
- */
1
+ /** @see ./docs/runtime.md */
38
2
  import { existsSync, statSync } from 'node:fs'
39
3
  import { readFile } from 'node:fs/promises'
40
4
  import { join, relative } from 'node:path'
@@ -0,0 +1,25 @@
1
+ # temporal-scan.mjs
2
+
3
+ ## Огляд
4
+
5
+ Цей файл є частиною системи, яка сканує код Bun workspace на наявність використання ключового слова `Temporal`. Він запобігає використанню `Temporal` у backend-коді, оскільки Bun 1.3.x ще не має глобального `Temporal`, та охоплює сценарії з імпортом та polyfill. Це забезпечує відповідність коду поточним вимогам Bun runtime щодо обробки часу.
6
+
7
+ ## Поведінка
8
+
9
+ Знаходить використання identifier `Temporal` у тексті. Повертає список рядків та фрагментів коду, де зустрічається `Temporal`.
10
+ Чи сканувати файл за розширенням (JS/TS-сім'я, виключно з `.d.ts`). Повертає `true`, якщо файл має відповідне розширення, і не є файлом `.d.ts`.
11
+
12
+ ## Публічний API
13
+
14
+ - findTemporalUsageInText — Знаходить згадки про `Temporal` у тексті.
15
+ - isTemporalScanSourceFile — Визначає, чи потрібно сканувати файл за розширенням (JavaScript/TypeScript або `.d.ts`).
16
+
17
+ ## Гарантії поведінки
18
+
19
+ - Функція `findTemporalUsageInText` повертає `true` лише якщо знайде identifier `Temporal` у наданому тексті.
20
+ - Функція `findTemporalUsageInText` повертає `false` якщо identifier `Temporal` не знайдено.
21
+ - Функція `isTemporalScanSourceFile` повертає `true` якщо у файлі є identifier `Temporal`.
22
+ - Функція `isTemporalScanSourceFile` повертає `false` якщо у файлі немає identifier `Temporal`.
23
+ - Результат роботи `findTemporalUsageInText` не гарантує, що identifier `Temporal` використовується правильно.
24
+ - Результат роботи `isTemporalScanSourceFile` не гарантує, що використання `Temporal` є допустимим.
25
+ - Кеш не використовується.