@nitra/cursor 3.27.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 (125) hide show
  1. package/CHANGELOG.md +11 -0
  2. package/package.json +1 -1
  3. package/rules/abie/js/applies.mjs +1 -5
  4. package/rules/abie/js/env_dns.mjs +1 -9
  5. package/rules/abie/js/firebase_hosting.mjs +1 -5
  6. package/rules/abie/js/hc_pairing.mjs +1 -8
  7. package/rules/abie/js/ua_http_route.mjs +1 -10
  8. package/rules/abie/js/ua_node_selector.mjs +1 -8
  9. package/rules/adr/js/hooks.mjs +1 -20
  10. package/rules/bun/js/layout.mjs +1 -19
  11. package/rules/capacitor/js/platforms.mjs +1 -23
  12. package/rules/changelog/js/consistency.mjs +1 -29
  13. package/rules/ci4/js/marksman_config.mjs +1 -19
  14. package/rules/docker/js/lint.mjs +1 -34
  15. package/rules/ga/docs/fix.md +4 -4
  16. package/rules/ga/js/docs/lint.md +3 -3
  17. package/rules/ga/js/docs/workflows.md +14 -14
  18. package/rules/ga/js/workflows.mjs +1 -16
  19. package/rules/ga/lint/docs/lint.md +9 -9
  20. package/rules/graphql/js/tooling.mjs +1 -9
  21. package/rules/hasura/js/internal_urls.mjs +1 -24
  22. package/rules/image-avif/js/avif_generation.mjs +1 -27
  23. package/rules/image-compress/js/package_setup.mjs +1 -18
  24. package/rules/js-bun-db/js/safety.mjs +1 -31
  25. package/rules/js-bun-redis/js/imports.mjs +1 -12
  26. package/rules/js-lint/js/docs/lint-findings.md +30 -0
  27. package/rules/js-lint/js/lint-findings.mjs +1 -7
  28. package/rules/js-lint/js/lint.mjs +1 -10
  29. package/rules/js-lint/js/tooling.mjs +1 -13
  30. package/rules/js-lint/js/utils_imports.mjs +1 -18
  31. package/rules/js-lint-ci/js/lint.mjs +1 -6
  32. package/rules/js-mssql/js/deps.mjs +1 -10
  33. package/rules/js-run/js/runtime.mjs +1 -37
  34. package/rules/js-run/lib/docs/temporal-scan.md +25 -0
  35. package/rules/k8s/js/manifests.mjs +1 -137
  36. package/rules/nginx-default-tpl/js/template.mjs +1 -18
  37. package/rules/npm-module/js/docs/header_doc_pointer.md +25 -0
  38. package/rules/npm-module/js/header_doc_pointer.mjs +82 -0
  39. package/rules/npm-module/js/package_structure.mjs +1 -28
  40. package/rules/npm-module/js/rule_meta.mjs +1 -10
  41. package/rules/npm-module/js/skill_meta.mjs +1 -13
  42. package/rules/php/js/tooling.mjs +1 -11
  43. package/rules/python/js/applies.mjs +1 -8
  44. package/rules/python/js/tooling.mjs +1 -21
  45. package/rules/rego/js/applies.mjs +1 -11
  46. package/rules/rust/js/applies.mjs +1 -7
  47. package/rules/security/js/sample_secret.mjs +1 -28
  48. package/rules/security/js/trufflehog.mjs +1 -8
  49. package/rules/style-lint/js/lint.mjs +1 -5
  50. package/rules/style-lint/js/tooling.mjs +1 -19
  51. package/rules/tauri/js/cargo_mutants_config.mjs +1 -20
  52. package/rules/tauri/js/tooling.mjs +1 -21
  53. package/rules/test/js/cargo_mutants_config.mjs +1 -12
  54. package/rules/test/js/location.mjs +1 -9
  55. package/rules/test/js/no-process-chdir.mjs +1 -21
  56. package/rules/test/js/no-relative-fs-path.mjs +1 -23
  57. package/rules/test/js/stryker_config.mjs +4 -25
  58. package/rules/test/js/vitest-config-pool-forks.mjs +1 -17
  59. package/rules/text/js/forbidden-prettier.mjs +1 -10
  60. package/rules/text/js/formatting.mjs +1 -31
  61. package/rules/vue/js/packages.mjs +1 -24
  62. package/scripts/docs/coverage-fix-extract.md +32 -0
  63. package/scripts/docs/lint-cli.md +25 -0
  64. package/scripts/docs/post-tool-use-fix.md +27 -0
  65. package/scripts/docs/rename-yaml-extensions.md +36 -0
  66. package/scripts/docs/skills-cli.md +35 -0
  67. package/scripts/docs/sync-claude-config.md +52 -0
  68. package/scripts/docs/sync-setup-bun-deps-action.md +26 -0
  69. package/scripts/docs/upgrade-nitra-cursor-and-install.md +29 -0
  70. package/scripts/docs/worktree-cli.md +46 -0
  71. package/scripts/lib/docs/assert-project-root.md +28 -0
  72. package/scripts/lib/docs/diff-added-lines.md +34 -0
  73. package/scripts/lib/docs/read-n-cursor-config-lite.md +28 -0
  74. package/scripts/lib/docs/resolve-target-files.md +34 -0
  75. package/scripts/lib/docs/root-notice.md +28 -0
  76. package/scripts/lib/docs/rule-meta-helpers.md +34 -0
  77. package/scripts/lib/docs/rule-meta.md +34 -0
  78. package/scripts/lib/docs/rule-predicates.md +30 -0
  79. package/scripts/lib/docs/run-conftest-batch.md +26 -0
  80. package/scripts/lib/docs/run-lint-step.md +25 -0
  81. package/scripts/lib/docs/run-rule-cli.md +27 -0
  82. package/scripts/lib/docs/run-rule.md +32 -0
  83. package/scripts/lib/docs/run-standard-lint.md +22 -0
  84. package/scripts/lib/docs/run-standard-rule.md +24 -0
  85. package/scripts/lib/docs/skill-meta.md +31 -0
  86. package/scripts/lib/docs/sync-gitignore-worktree.md +31 -0
  87. package/scripts/lib/docs/template.md +40 -0
  88. package/scripts/lib/docs/timing-summary.md +24 -0
  89. package/scripts/lib/docs/workspaces.md +30 -0
  90. package/scripts/lib/docs/worktree-notice.md +27 -0
  91. package/scripts/lib/docs/worktree.md +38 -0
  92. package/scripts/utils/docs/ast-scan-utils.md +50 -0
  93. package/scripts/utils/docs/ensure-gitignore-entries.md +28 -0
  94. package/scripts/utils/docs/find-package-json-paths.md +26 -0
  95. package/scripts/utils/docs/lock-cache-dir.md +25 -0
  96. package/scripts/utils/docs/pass.md +25 -0
  97. package/scripts/utils/docs/resolve-cargo-manifest.md +23 -0
  98. package/scripts/utils/docs/resolve-cmd.md +29 -0
  99. package/scripts/utils/docs/resolve-js-root.md +25 -0
  100. package/scripts/utils/docs/test-helpers.md +36 -0
  101. package/scripts/utils/docs/walk-cache.md +27 -0
  102. package/scripts/utils/docs/walkDir.md +32 -0
  103. package/scripts/utils/docs/with-lock.md +25 -0
  104. package/scripts/utils/docs/worktree-fingerprint.md +27 -0
  105. package/skills/docgen/js/docgen-batch.mjs +95 -0
  106. package/skills/docgen/js/docgen-extract.mjs +33 -18
  107. package/skills/docgen/js/docgen-gen.mjs +125 -98
  108. package/skills/docgen/js/docgen-ignore.mjs +1 -6
  109. package/skills/docgen/js/docgen-prompts.mjs +33 -22
  110. package/skills/docgen/js/docgen-scan.mjs +1 -8
  111. package/skills/docgen/js/docs/docgen-extract.md +28 -0
  112. package/skills/docgen/js/docs/docgen-gen.md +41 -0
  113. package/skills/docgen/js/docs/docgen-ignore.md +24 -0
  114. package/skills/docgen/js/docs/docgen-prompts.md +24 -0
  115. package/skills/docgen/js/docs/docgen-scan.md +48 -0
  116. package/skills/fix/js/docs/llm-worker.md +27 -0
  117. package/skills/fix/js/docs/orchestrator.md +32 -0
  118. package/skills/fix/js/docs/t0.md +29 -0
  119. package/skills/fix/js/llm-worker.mjs +64 -29
  120. package/skills/fix/js/orchestrator.mjs +45 -54
  121. package/skills/fix/js/t0.mjs +16 -32
  122. package/skills/start-check/js/check.mjs +1 -16
  123. package/skills/start-check/js/docs/check.md +34 -0
  124. package/skills/taze/js/diff.mjs +1 -15
  125. package/skills/taze/js/docs/diff.md +33 -0
@@ -1,31 +1,4 @@
1
- /**
2
- * FS-частина правила `security`: concern `sample_secret`.
3
- *
4
- * Перевіряє, що фейкові credential-значення у *прикладних* файлах записані як
5
- * канонічний placeholder `sample-secret`, а не як bare `secret`.
6
- *
7
- * `sample-secret` містить підрядок `sample`, який є у вшитому списку
8
- * `DefaultFalsePositives` TruffleHog — таке значення сканер відсіює
9
- * гарантовано й незалежно від версії. Bare `secret` наразі не фіксується сканером
10
- * лише тому, що випадково присутнє у словнику `fp_words.txt`; це крихка поведінка,
11
- * що залежить від версії інструмента, на яку не варто покладатися.
12
- *
13
- * Прикладними вважаються файли, чий basename має суфікс `.example` / `.sample`
14
- * / `.template` / `.dist` або infix `.example.` / `.sample.` / `.template.`, а
15
- * також будь-які файли всередині каталогів `fixtures` / `fixture` /
16
- * `__fixtures__`. Решта файлів не сканується — там `secret` майже завжди
17
- * частина реального коду, а не placeholder.
18
- *
19
- * Порушенням є лише `secret` у *позиції значення* — одразу після `=`, `:` чи
20
- * `=>` (з опційними лапками). Імена ключів (`client_secret`, `JWT_SECRET`) не
21
- * чіпаються: матч прив'язаний до значення, не до ключа.
22
- *
23
- * Чому regex, а не AST: прикладні файли — різнорідні конфіги (`.env`, YAML,
24
- * JSON, TOML, plain `.dist`), єдиного AST для них немає, тож скан порядковий.
25
- * Чому JS, а не Rego: щоб знайти прикладні файли, треба обійти дерево
26
- * (`readdir`), а вміст — неструктурований текст (conftest парсить лише
27
- * структуровані документи).
28
- */
1
+ /** @see ./docs/sample_secret.md */
29
2
  import { readFile } from 'node:fs/promises'
30
3
  import { relative, sep } from 'node:path'
31
4
 
@@ -1,11 +1,4 @@
1
- /**
2
- * FS-частина правила `security`.
3
- *
4
- * Перевіряє:
5
- * - наявність `package.json` (структуру валідує policy security.package_json);
6
- * - наявність `.trufflehog-exclude` у корені та subset канонічних patterns
7
- * (text-subset, бо `.trufflehog-exclude` — plain text, не структурований).
8
- */
1
+ /** @see ./docs/trufflehog.md */
9
2
  import { existsSync } from 'node:fs'
10
3
  import { readFile } from 'node:fs/promises'
11
4
  import { dirname, join } from 'node:path'
@@ -1,8 +1,4 @@
1
- /**
2
- * Quick-крок lint правила style-lint: stylelint --fix по css/scss/vue.
3
- *
4
- * `files` (quick) → лише style-файли з них; undefined (ci) → весь glob `**\/*.{css,scss,vue}`.
5
- */
1
+ /** @see ./docs/lint.md */
6
2
  import { spawnSync } from 'node:child_process'
7
3
 
8
4
  const STYLE_EXT_RE = /\.(?:css|scss|vue)$/u
@@ -1,22 +1,4 @@
1
- /**
2
- * Перевіряє CSS/SCSS лінт за правилом style-lint.mdc.
3
- *
4
- * **Що тут лишилося** (FS / cross-file — не покривається conftest):
5
- * - наявність зовнішнього файлу конфігу stylelint (`.stylelintrc.*`,
6
- * `stylelint.config.js`) як альтернатива полю `stylelint` у `package.json`
7
- * (cross-file: треба знати, чи є поле, чи немає);
8
- * - `.stylelintignore` у корені.
9
- *
10
- * **Що покрила Rego** (`npx \@nitra/cursor check`):
11
- * - `npm/policy/style_lint/package_json/` — скрипт `lint-style` через `npx stylelint`,
12
- * `@nitra/stylelint-config` у `devDependencies`, поле `stylelint.extends`;
13
- * - `npm/policy/style_lint/lint_style_yml/` — `npx stylelint` у `run` workflow;
14
- * - `npm/policy/style_lint/vscode_extensions/` — `stylelint.vscode-stylelint`
15
- * у `recommendations` `.vscode/extensions.json`;
16
- * - `npm/policy/style_lint/vscode_settings/` — `css.validate`/`scss.validate`/
17
- * `less.validate: false` у `.vscode/settings.json`.
18
- * @param {string} cwd корінь репозиторію
19
- */
1
+ /** @see ./docs/tooling.md */
20
2
  import { existsSync } from 'node:fs'
21
3
  import { readFile } from 'node:fs/promises'
22
4
  import { join } from 'node:path'
@@ -1,23 +1,4 @@
1
- /**
2
- * Концерн `cargo_mutants_config` правила tauri (tauri.mdc): для кожного
3
- * `<workspace>/src-tauri/Cargo.toml` без дублювання гарантує наявність
4
- * Tauri-specific cargo-mutants налаштувань у `<workspace>/src-tauri/.cargo/mutants.toml`.
5
- *
6
- * Семантика (фіксована між Tauri-проєктами):
7
- * - `src/main.rs` — binary shell entrypoint (smoke/e2e, не mutation unit);
8
- * - `src/**\/{android,ios,mobile}.rs` — mobile plugin bridge / platform glue;
9
- * - `src/**\/{macos,windows,linux,desktop}.rs` — desktop platform bridge / OS integration glue.
10
- *
11
- * Self-gating: silently skip, якщо в monorepo не знайдено жодного
12
- * `<ws>/src-tauri/Cargo.toml` (test rule сам створить нейтральний baseline там,
13
- * де потрібно).
14
- *
15
- * Ідемпотентність:
16
- * - якщо файл відсутній — створює з Tauri-canonical baseline;
17
- * - якщо файл існує і всі канонічні ключі вже є — `manual cargo-mutants config preserved`;
18
- * - якщо файл існує, але якихось канонічних top-level ключів немає — додає
19
- * лише відсутні ключі окремим блоком у кінці; існуючих значень не торкається.
20
- */
1
+ /** @see ./docs/cargo_mutants_config.md */
21
2
  import { existsSync } from 'node:fs'
22
3
  import { mkdir, readFile, writeFile } from 'node:fs/promises'
23
4
  import { dirname, join, relative } from 'node:path'
@@ -1,24 +1,4 @@
1
- /**
2
- * Перевіряє інструментарій Tauri (tauri.mdc): VSCode `extensions.json` для
3
- * проєктів, у яких є маркер Tauri.
4
- *
5
- * Cross-file gating (JS):
6
- * 1. Tauri-маркер визначаємо обходом усіх workspace-пакетів через
7
- * `getMonorepoPackageRootDirs()` (корінь + workspaces). Кожен workspace
8
- * перевіряється за **будь-яким** з:
9
- * - існує каталог `<ws>/src-tauri/`;
10
- * - існує файл `<ws>/src-tauri/Cargo.toml`;
11
- * - існує файл `<ws>/src-tauri/tauri.conf.json`;
12
- * - існує файл `<ws>/tauri.conf.json` (legacy flat-layout);
13
- * - `<ws>/package.json#dependencies` чи `devDependencies` містить ключ
14
- * з префіксом `@tauri-apps/`.
15
- * 2. Якщо маркера немає — пропустити перевірку (tauri-tooling не вимагається).
16
- * 3. Інакше — для `.vscode/extensions.json` зробити FS-existence + делегувати
17
- * content `rego.tauri.vscode_extensions` через `runConftestBatch`.
18
- *
19
- * Rego-полісі глобально без `target.json` поруч (не auto-discoverable через `n-cursor fix`) — це conditional
20
- * правило. Plan B: Rego-authoritative + JS-orchestrator з `runConftestBatch`.
21
- */
1
+ /** @see ./docs/tooling.md */
22
2
  import { existsSync, statSync } from 'node:fs'
23
3
  import { readFile } from 'node:fs/promises'
24
4
  import { join } from 'node:path'
@@ -1,15 +1,4 @@
1
- /**
2
- * Концерн `cargo_mutants_config` правила test (test.mdc): якщо `rust` присутнє
3
- * в `.n-cursor.json#rules` і не у `disable-rules` — визначає ВСІ Cargo.toml
4
- * (cwd і всі workspaces, з підтримкою Tauri-патерну) і копіює canonical
5
- * baseline `.cargo/mutants.toml` у каталог кожного manifest'а, якщо файлу немає.
6
- *
7
- * Self-gating: концерн silently skips коли `rust` не enabled.
8
- * Якщо `rust` enabled, але жодного Cargo.toml не знайдено — теж silently skip
9
- * (manifest може з'явитися пізніше; це не помилка).
10
- *
11
- * Baseline — порожній файл з коментарем; cargo-mutants має робочі defaults.
12
- */
1
+ /** @see ./docs/cargo_mutants_config.md */
13
2
  import { existsSync } from 'node:fs'
14
3
  import { copyFile, mkdir } from 'node:fs/promises'
15
4
  import { dirname, join, relative } from 'node:path'
@@ -1,12 +1,4 @@
1
- /**
2
- * Перевіряє, що всі `*.test.mjs` лежать у каталозі `tests/` (а не поряд із джерельним файлом).
3
- *
4
- * Конвенція (test.mdc): `dir/foo.mjs` → тест у `dir/tests/foo.test.mjs`.
5
- * `*_test.rego` виключені: Rego unit-тести живуть поряд із полісі (OPA community convention).
6
- *
7
- * Пропускає: `node_modules`, `.git`, `dist`, `build`, `.venv`, `venv` (через `walkDir`)
8
- * і шляхи з `.n-cursor.json:ignore`.
9
- */
1
+ /** @see ./docs/location.md */
10
2
  import { basename, dirname, relative } from 'node:path'
11
3
 
12
4
  import { createCheckReporter } from '../../../scripts/lib/check-reporter.mjs'
@@ -1,24 +1,4 @@
1
- /**
2
- * Заборона `process.chdir(...)` у тестах.
3
- *
4
- * Контекст (test.mdc, секція "Заборона `process.chdir` у тестах"):
5
- * `process.chdir` — process-wide мутація. Vitest за замовчуванням ставить
6
- * `pool: 'threads'`, де workers ділять один процес: паралельний test file
7
- * може перехопити cwd сусіда посеред FS- або `git`-операції. Реальний
8
- * інцидент — `git init`+`git commit` із tmp-фікстури `withTmpCwd` потрапив у
9
- * реальний робочий репозиторій і створив rogue commit з автором `test
10
- * <test@test>`. Тому канон: `withTmpDir(async dir => ...)` зі
11
- * `scripts/utils/test-helpers.mjs` (без `chdir`) + явні `cwd: dir` у child-
12
- * процесах + `await check(dir)` для concern-функцій.
13
- *
14
- * Цей concern сканує `**\/*.test.{js,mjs}` і падає на будь-яке вживання
15
- * `process.chdir(`. Виняток — коментарі/документація: regex знаходить лише
16
- * викликний паттерн (відкривна дужка), тож згадки у JSDoc типу
17
- * "не використовуй `process.chdir`" не тригерять.
18
- *
19
- * Скіпи: `node_modules`, `.git`, `dist`, `build`, `.venv`, `venv` (через
20
- * `walkDir`) і шляхи з `.n-cursor.json:ignore`.
21
- */
1
+ /** @see ./docs/no-process-chdir.md */
22
2
  import { readFile } from 'node:fs/promises'
23
3
  import { basename, relative } from 'node:path'
24
4
 
@@ -1,26 +1,4 @@
1
- /**
2
- * Заборона **relative-path** аргументів у FS-функціях усередині тестів.
3
- *
4
- * Контекст (test.mdc, секція "Заборона `process.chdir` у тестах"):
5
- * Після видалення `withTmpCwd` усі тести отримують `dir` параметром і мають
6
- * будувати **абсолютні** шляхи через `join(dir, …)`. Якщо хтось забуде префікс
7
- * і напише `writeFile('foo.json', …)` чи `copyFile(src, 'foo.json')` —
8
- * relative-path резолвиться у `process.cwd()` (= `npm/`), що зливає тестову
9
- * фікстуру у production tree. Інцидент v1.28.0: `tests/check-rule-fixtures.test.mjs`
10
- * залишив `copyFile(src, 'values-dev.ini')` і `copyFile(src, 'default.conf.template')` —
11
- * створило файли `npm/values-dev.ini` і `npm/default.conf.template`.
12
- *
13
- * Сканер AST-based (oxc-parser): знаходить виклики `node:fs`/`node:fs/promises`
14
- * функцій із **string literal** аргументом-шляхом, який НЕ починається з:
15
- * - `/`, `\\` — POSIX/Windows absolute;
16
- * - `file:`/`http`/`data:` — URL-схема (передається до `new URL(...)`);
17
- * - `${…}` (template-literal з виразом) і `\`…\${dir}\`` патерни — обчислений шлях;
18
- * - `:` для Windows-літер диску `C:\…` (рідко в тестах, але legit).
19
- * Виклики, чий path-аргумент — НЕ literal (CallExpression `join(...)`, BinaryExpression,
20
- * Identifier, MemberExpression) — пропускаємо: припускаємо що це абсолютний шлях.
21
- *
22
- * Скани: `**\/*.test.{js,mjs}` з загальними `walkDir` skip + `.n-cursor.json#ignore`.
23
- */
1
+ /** @see ./docs/no-relative-fs-path.md */
24
2
  import { readFile } from 'node:fs/promises'
25
3
  import { basename, relative } from 'node:path'
26
4
 
@@ -1,27 +1,4 @@
1
- /**
2
- * Концерн `stryker_config` правила test (test.mdc): якщо `js-lint` присутнє в
3
- * `.n-cursor.json#rules` і не у `disable-rules` — визначає ВСІ JS-roots
4
- * (всі workspaces з package.json, або cwd у single-package) і копіює canonical
5
- * baseline `stryker.config.mjs` + `vitest.config.js` у кожен root, де файлу немає.
6
- *
7
- * Для JS-roots із `.vue` файлами (Vue 3 + `<script setup>`) копіюється vue-варіант
8
- * baseline, який реєструє локальний Ignore-плагін `vue-macros` — інакше Stryker
9
- * огортає виклики `defineProps`/`defineEmits`/... у coverage-тернарник і
10
- * `@vue/compiler-sfc` падає при компіляції SFC. Плагін копіюється у той самий
11
- * jsRoot як `stryker-vue-macros-ignorer.mjs`.
12
- *
13
- * Augment (drift-hole): якщо у Vue-root `stryker.config.mjs` уже існував (проєкт
14
- * мав non-vue config ще до 3.x Vue-підтримки), `ensureBaselineFile` його не
15
- * перетирає — тож `augmentVueStrykerConfig` точково вставляє `plugins`/`ignorers`
16
- * у наявний файл (string-splice за AST-аналізом), зберігаючи решту полів і
17
- * коментарів. Idempotent: повторний прогон нічого не дублює.
18
- *
19
- * Self-gating: концерн silently skips коли `js-lint` не enabled — це навмисно,
20
- * щоб не шуміти у single-language проєктах без JS coverage tooling.
21
- *
22
- * Baseline — мінімум для запуску Stryker з vitest-runner + perTest; mutate-патерни
23
- * лишаються на Stryker defaults (`src/**\/*.{js,mjs,ts,jsx,tsx,cjs}`).
24
- */
1
+ /** @see ./docs/stryker_config.md */
25
2
  import { existsSync } from 'node:fs'
26
3
  import { copyFile, glob, readFile, writeFile } from 'node:fs/promises'
27
4
  import { dirname, join, relative } from 'node:path'
@@ -310,7 +287,9 @@ async function augmentVueStrykerConfig(reporter, cwd, jsRoot) {
310
287
  try {
311
288
  recheck = parseSync(target, next, { lang: 'js', sourceType: 'module' })
312
289
  } catch (error) {
313
- reporter.fail(`stryker.config.mjs: augment дав некоректний результат (${rel}): ${error.message} — відкат, додай вручну`)
290
+ reporter.fail(
291
+ `stryker.config.mjs: augment дав некоректний результат (${rel}): ${error.message} — відкат, додай вручну`
292
+ )
314
293
  return
315
294
  }
316
295
  if (recheck.errors?.length) {
@@ -1,20 +1,4 @@
1
- /**
2
- * `vitest.config.js` має ставити `pool: 'forks'` — defense-in-depth для
3
- * race-bug у `process.cwd()` (test.mdc, секція "Заборона `process.chdir` у тестах").
4
- *
5
- * Чому не достатньо самої заборони `process.chdir(`: third-party код у залежностях
6
- * може робити chdir всередині vitest worker'а. У `pool: 'threads'` (default) усі
7
- * workers ділять один процес → race на `process.cwd()` між паралельними test
8
- * files. `pool: 'forks'` ізолює кожен test file у власному child-процесі.
9
- *
10
- * Перевірка — substring у source-тексті `vitest.config.js`. Не парсимо JS AST,
11
- * бо це може бути будь-який export-формат (ESM default, named, CommonJS).
12
- * Достатньо знайти `pool:` із значенням `'forks'`/`"forks"` (whitespace дозволений).
13
- *
14
- * Скіпи: правило не застосовне, якщо `vitest.config.js` не існує (нема vitest
15
- * у проєкті) — це не помилка, лише skip. Якщо файл є — `pool: 'forks'`
16
- * обов'язковий.
17
- */
1
+ /** @see ./docs/vitest-config-pool-forks.md */
18
2
  import { existsSync } from 'node:fs'
19
3
  import { readFile } from 'node:fs/promises'
20
4
  import { join } from 'node:path'
@@ -1,13 +1,4 @@
1
- /**
2
- * Suspect FS-перевірка: жоден Prettier-артефакт у корені проєкту не дозволений.
3
- *
4
- * `text.mdc` забороняє `prettier`, `@nitra/prettier-config` і всі прояви Prettier-конфігів.
5
- * Rego-полісі `text.package_json` ловить scripts/dependencies/devDependencies; цей concern
6
- * ловить FS-сторону — конфіги й ignore-файли, які runner Prettier зчитує автоматично.
7
- *
8
- * Список синхронізовано з конфіг-форматами Prettier 3.x
9
- * (https://prettier.io/docs/configuration). Якщо Prettier додасть новий формат — додай рядок.
10
- */
1
+ /** @see ./docs/forbidden-prettier.md */
11
2
  import { existsSync } from 'node:fs'
12
3
  import { join } from 'node:path'
13
4
 
@@ -1,34 +1,4 @@
1
- /**
2
- * Перевіряє текстовий стек і форматування за правилом text.mdc.
3
- *
4
- * **Що тут лишилося** (FS / VSCode-конфіги / markdown / лінт-скрипт):
5
- * - `.v8rignore` (текстовий формат, рядки шляхів);
6
- * - `.vscode/extensions.json` рекомендації (markdownlint, oxc, shellcheck) і
7
- * `.vscode/settings.json` (`editor.formatOnSave`, `[lang].editor.defaultFormatter`);
8
- * - наявність FS-файлів `.oxfmtrc.json`, `.cspell.json`, `.markdownlint-cli2.jsonc`,
9
- * `package.json` (саме *існування* — структуру вже валідує Rego);
10
- * - абзац про український апостроф у `.cursor/rules/n-text.mdc` /
11
- * `npm/mdc/text.mdc` (markdown-текст, не JSON/YAML);
12
- * - складна валідація скрипта `lint-text` (cspell, markdownlint, v8r у трьох
13
- * варіантах, run-shellrules/text/fix.mjs, обовʼязкові glob-и);
14
- * - workflow `lint-text.yml` має крок `bun run lint-text` (структура — rego `text.lint_text`).
15
- *
16
- * **Що покрила Rego** (`npx \@nitra/cursor check`):
17
- * - `npm/policy/text/oxfmtrc/` — обовʼязкові ключі `.oxfmtrc.json` і канонічні
18
- * значення (semi/singleQuote/tabWidth/useTabs/printWidth) + `ignorePatterns`
19
- * канонічні glob-и;
20
- * - `npm/policy/text/cspell/` — `.cspell.json` `version "0.2"`, `language`,
21
- * імпорт `@nitra/cspell-dict`, заборона `@cspell/dict-*`, обовʼязкові
22
- * `ignorePaths`;
23
- * - `npm/policy/text/markdownlint/` — `.markdownlint-cli2.jsonc` `gitignore: true`
24
- * (працює лише якщо файл — валідний JSON без коментарів);
25
- * - `npm/policy/text/package_json/` — заборона Prettier (`prettier` поле +
26
- * `prettier`/`@nitra/prettier-config` у залежностях), `@nitra/cspell-dict ^2.0.0+`
27
- * у `devDependencies`, заборона `markdownlint-cli2` у залежностях.
28
- * - `npm/policy/bun/package_json/` — у `devDependencies` лише `@nitra/*`
29
- * (раніше дублювалося тут).
30
- * @param {string} cwd корінь репозиторію
31
- */
1
+ /** @see ./docs/formatting.md */
32
2
  import { existsSync } from 'node:fs'
33
3
  import { readFile } from 'node:fs/promises'
34
4
  import { join } from 'node:path'
@@ -1,27 +1,4 @@
1
- /**
2
- * Знаходить пакети з `vue` у dependencies і перевіряє їх за правилом vue.mdc.
3
- *
4
- * Вміст `vite.config`, editor-файли для Vite client types, у репозиторії —
5
- * рекомендацію розширення Vue.volar.
6
- *
7
- * Залежності Vue/Vite (`vite >= 8`, `@vitejs/plugin-vue`, `vue-macros`,
8
- * `unplugin-auto-import`, `vite-plugin-vue-layouts-next`, заборона `esbuild`) —
9
- * у policy `vue.package_json`.
10
- *
11
- * У кожному Vue+Vite-пакеті очікується `src/vite-env.d.ts` з `/// <reference types="vite/client" />`
12
- * та `jsconfig.json` у корені пакета (типи для імпортів асетів у `.vue`).
13
- *
14
- * У `vite.config.*` заборонено використовувати `process.env.npm_lifecycle_event` (Bun не підставляє його як npm),
15
- * натомість використовуй `mode` з `defineConfig(({ mode }) => ...)`.
16
- *
17
- * Заборонені явні value-імпорти з `vue` у джерелах пакета — сканування `.vue`/`.ts`/`.js` тощо
18
- * через **oxc-parser** (`module.staticImports`; див. `./vue-forbidden-imports.mjs`); дозволені лише type-only та side-effect `import 'vue'`.
19
- *
20
- * Окремо в `.vue` SFC заборонено імпорти Node-нативних модулів — `node:*` префікс або bare-ім’я
21
- * вбудованого модуля Node (`fs`, `path`, `timers/promises` тощо). Vue SFC виконується у браузері,
22
- * де Node API недоступне; такий код треба тримати у server-side утілітах.
23
- * @param {string} cwd корінь репозиторію
24
- */
1
+ /** @see ./docs/packages.md */
25
2
  import { existsSync } from 'node:fs'
26
3
  import { readFile } from 'node:fs/promises'
27
4
  import { join, relative } from 'node:path'
@@ -0,0 +1,32 @@
1
+ # coverage-fix-extract.mjs
2
+
3
+ ## Огляд
4
+
5
+ Цей файл витягує вцілілі мутанти з файлу `COVERAGE.md` у форматі JSON. Витягнуті дані надаються агенту для вирішення проблем з покриттям, зменшуючи навантаження на LLM-оркестратор та забезпечуючи ефективний обмін інформацією. Це ключовий компонент процесу `n-coverage-fix`, що дозволяє агенту швидко реагувати на зміни в покритті.
6
+
7
+ ## Поведінка
8
+
9
+ parseSurvivedBlock: Витягує JSON-масив вцілілих мутантів із тексту `COVERAGE.md`.
10
+ readSurvived: Читає `COVERAGE.md` із кореня проєкту і повертає групи вцілілих.
11
+ buildIndex: Згортає групи вцілілих у компактний index `[{file, mutants}]`.
12
+ runCoverageFixCli: CLI: `index` друкує компактний JSON-масив, `slice --file <path>` — промпт для одного файлу.
13
+
14
+ ## Публічний API
15
+
16
+ - parseSurvivedBlock — Витягує дані про вцілілих мутантів з `COVERAGE.md` у форматі JSON.
17
+ - readSurvived — Зчитує `COVERAGE.md` та повертає структуровані дані про вцілілих.
18
+ - buildIndex — Створює компактний індекс у форматі JSON, що містить інформацію про файли та мутанти.
19
+ - runCoverageFixCli — CLI для друку та обрізки даних з `COVERAGE.md`.
20
+
21
+ ## Гарантії поведінки
22
+
23
+ - Скрипт парсить файл `COVERAGE.md`.
24
+ - Результатом парсингу є об'єкт з інформацією про вцілілі мутанти.
25
+ - Скрипт повертає об'єкт, якщо файл `COVERAGE.md` існує та може бути успішно прочитаний.
26
+ - Якщо файл `COVERAGE.md` не існує, скрипт повертає порожній об'єкт.
27
+ - Скрипт не змінює вміст файлу `COVERAGE.md`.
28
+ - Скрипт не запускає Stryker.
29
+ - Скрипт не генерує винятків.
30
+ - Скрипт не використовує кешування.
31
+ - Використання команди `index` повертає мінімальний об'єкт, що містить інформацію про вцілілі мутанти.
32
+ - Використання команди `slice --file <path>` повертає промпт для одного файлу, що містить контекст ±3 рядки.
@@ -0,0 +1,25 @@
1
+ # lint-cli.mjs
2
+
3
+ ## Огляд
4
+
5
+ Файл забезпечує оркестрацію виконання правил лінтингу для проєкту. Він сканує правила, визначені в файлах `meta.json`, та викликає відповідні файли `lint.mjs` для перевірки коду. Це дозволяє автоматично виявляти та повідомляти про помилки в коді на основі набору визначених правил.
6
+
7
+ ## Поведінка
8
+
9
+ selectLintRules: Вибирає id правил для фази, алфавітно.
10
+ runLint: Запускає lint-оркестрацію. Збирає змінені файли, якщо потрібно, та запускає lint для кожного правила, яке відповідає вибраній фазі.
11
+
12
+ ## Публічний API
13
+
14
+ - selectLintRules — Вибирає набір правил для перевірки.
15
+ - runLint — Запускає процес перевірки.
16
+
17
+ ## Гарантії поведінки
18
+
19
+ - Оркестратор запускає правила лінтингу, визначені в файлах `rules/<id>/meta.json`.
20
+ - Для режиму `quick` оркестратор обробляє лише змінені файли, визначені за допомогою `git diff`.
21
+ - Для режиму `ci` оркестратор обробляє весь проєкт.
22
+ - Порядок виконання правил визначається алфавітним порядком імен файлів `rules/<id>/js/lint.mjs`.
23
+ - Перший виклик функції `lint` повертає ненульове значення, що призводить до зупинки виконання.
24
+ - Режим `quick` не використовує кешування.
25
+ - Режим `ci` не використовує кешування.
@@ -0,0 +1,27 @@
1
+ # post-tool-use-fix.mjs
2
+
3
+ ## Огляд
4
+
5
+ Файл забезпечує точкову маршрутизацію `npx @nitra/cursor fix` для конкретних файлів, що були змінені. Він запускає цей процес після редагування, щоб уникнути затримки, спричиненої попереднім синхронним хуком. Це дозволяє швидко та ефективно виправляти правила стилю коду для змінених файлів.
6
+
7
+ ## Поведінка
8
+
9
+ `routeFilePathToRules`: повертає список ID правил `npm/rules/<id>`, які слід застосувати до вказаного шляху файлу, використовуючи відповідні шаблони glob.
10
+ `runPostToolUseFixCli`: запускає `npx @nitra/cursor fix` з переліченими правилами, отримуючи вхідні дані з stdin, та повертає exit-код запущеного процесу. Якщо не вдається запустити `fix`, повертає 1.
11
+ `readStdin`: зчитує вміст stdin до EOF, повертаючи рядок UTF-8. Якщо stdin TTY, повертає порожній рядок.
12
+
13
+ ## Публічний API
14
+
15
+ - routeFilePathToRules — Знаходить правила, які відповідають шляху файлу, та повертає їх. Якщо жодного правила не знайдено, повертає порожній масив.
16
+ - runPostToolUseFixCli — Запускає інструмент для виправлення помилок, викликаний з `bin/n-cursor.js` при певних умовах. Дозволяє передавати дані для тестування та замінити стандартну функцію запуску процесу.
17
+
18
+ ## Гарантії поведінки
19
+
20
+ - Приймає JSON із шляхом файлу як вхідні дані.
21
+ - Якщо файл не має маршруту, повертає `true`.
22
+ - Інакше запускає `npx --no @nitra/cursor fix` з переданими правилами.
23
+ - Не блокує потік (turn).
24
+ - Повертає `false` у разі невдачі запуску `npx`.
25
+ - Не кидає винятків.
26
+ - Ігнорує шляхи `.github` та `.git`.
27
+ - Не використовує кешування.
@@ -0,0 +1,36 @@
1
+ # rename-yaml-extensions.mjs
2
+
3
+ ## Огляд
4
+
5
+ Цей файл перейменовує розширення файлів YAML у репозиторіях, відповідно до узгоджених правил. Він автоматизує процес зміни розширення файлів `.yml` на `.yaml` для файлів, що відповідають певним шаблонам шляхів, зокрема для маніфестів Kubernetes та workflow-файлів GitHub. Це забезпечує узгодженість форматування YAML у репозиторії.
6
+
7
+ ## Поведінка
8
+
9
+ - `posixRelFromRoot`: Обчислює відносний шлях від кореня, замінюючи `\` на `/`. Повертає `null`, якщо шлях поза коренем.
10
+ - `pathMatchesK8sYml`: Перевіряє, чи шлях містить сегмент `k8s` та має розширення `.yml`.
11
+ - `pathMatchesGithubYaml`: Перевіряє, чи шлях містить сегмент `.github` та має розширення `.yaml`.
12
+ - `replaceExtension`: Замінює останнє розширення файлу на вказане, додаючи крапку.
13
+ - `collectRenameOps`: Збирає операції перейменування, обходячи репозиторій, ігноруючи `node_modules`, `.git`, `dist`, `coverage`, `.turbo`, `.next`.
14
+ - `renameYamlExtensions`: Виконує перейменування, симулюючи або реалізуючи перейменування, на основі правил k8s/github, обходячи вказані каталоги.
15
+ - `parseRenameYamlArgs`: Розбирає аргументи командного рядка `--dry-run` та `--root`.
16
+
17
+ ## Публічний API
18
+
19
+ - posixRelFromRoot — Повертає відносний шлях від кореня файлової системи, або `null`, якщо шлях знаходиться за межами кореня.
20
+ - pathMatchesK8sYml — Перевіряє, чи відповідає шлях формату YAML-маніфестів Kubernetes.
21
+ - pathMatchesGithubYaml — Перевіряє, чи відповідає шлях формату YAML-файлів `.github`.
22
+ - replaceExtension — Замінює розширення файлу на вказане.
23
+ - renameYamlExtensions — Перейменовує YAML-файли відповідно до правил Kubernetes та `.github`.
24
+ - parseRenameYamlArgs — Розбирає аргументи командного рядка для команди перейменування.
25
+
26
+ ## Гарантії поведінки
27
+
28
+ - Файл `bin/rename-yaml-extensions.mjs` перейменовує розширення YAML файлів.
29
+ - Перейменування відбувається за двома сценаріями:
30
+ - Файли з сегментом шляху `k8s` та суфіксом `.yml` перейменовуються на `.yaml`.
31
+ - Файли з сегментом `.github` та суфіксом `.yaml` перейменовуються на `.yml`.
32
+ - Обхід шляхів: `node_modules`, `.git`, `dist`, `coverage`, `.turbo`, `.next` не обробляються.
33
+ - Аргументи CLI: `--dry-run`, `--root`
34
+ - Повертає `false` у разі невдачі.
35
+ - Не кидає винятків.
36
+ - Не використовує кешування.
@@ -0,0 +1,35 @@
1
+ # skills-cli.mjs
2
+
3
+ ## Огляд
4
+
5
+ Це інструмент для запуску скілів з пакету `@nitra/cursor` без синхронізації правил. Він збирає інструкції скілу та контекст проєкту для генерації промптів, які потім можуть бути використані для отримання відповідей від Claude або інших агентів. Інструмент забезпечує зручний інтерфейс командного рядка для взаємодії з скілами.
6
+
7
+ ## Поведінка
8
+
9
+ - `normalizeSkillId`: Перетворює вхідний `name` скілу (можливо з префіксом `n-`) в нормалізований `id` каталогу.
10
+ - `listSkillIds`: Повертає відсортований список `id` каталогів скілів у каталозі `skills/` пакета, фільтруючи лише ті, що мають файл `SKILL.md`.
11
+ - `getSkillMdPath`: Створює повний шлях до файлу `SKILL.md` скілу на основі `skillsRoot` та `skillId`.
12
+ - `readIfExists`: Перевіряє існування файлу за шляхом `path` та повертає його вміст, якщо файл існує, інакше повертає `null`.
13
+ - `buildSkillPrompt`: Збирає промпт для LLM, включаючи інструкції скілу, текст завдання, та контекст проєкту (package.json, tsconfig.json, .n-cursor.json).
14
+ - `runLlmCli`: Запускає LLM CLI (`claude` або `cursor-agent`) з наданим промптом та робочим каталогом проєкту.
15
+ - `resolveBundledPackageRoot`: Визначає абсолютний шлях до кореня пакета `@nitra/cursor`, використовуючи `import.meta.url` для визначення кореня.
16
+ - `runSkillsCli`: Обробляє аргументи командного рядка для запуску скілів, викликає відповідні функції для збору промптів та запуску LLM CLI.
17
+
18
+ ## Публічний API
19
+
20
+ - normalizeSkillId: Перетворює ID на стандартний формат.
21
+ - listSkillIds: Повертає список ID навичок.
22
+ - buildSkillPrompt: Створює запит для навички.
23
+ - resolveBundledPackageRoot: Знаходить базову директорію пакета `@nitra/cursor`.
24
+ - runSkillsCli: Запускає CLI для навичок.
25
+
26
+ ## Гарантії поведінки
27
+
28
+ - Запускає скіли пакета `@nitra/cursor` без синхронізації правил.
29
+ - Читає скіли з файлів `npm/skills/<id>/SKILL.md` або кешу `npx`.
30
+ - Збирає інструкцію скілу та контекст проєкту (package.json, tsconfig.json, .n-cursor.json) для створення промпту.
31
+ - Використовує промпт для генерації відповіді, яка може бути виведена в stdout або делегована `cursor-agent` / `claude`.
32
+ - Підтримує команди `skill list`, `skill taze`, `skill cursor taze`, `skill cursor taze "онови залежності"`, `skill claude taze`.
33
+ - Повертає `false` або `null` у разі невдачі виконання.
34
+ - Не кидає винятки.
35
+ - Не використовує кешування.
@@ -0,0 +1,52 @@
1
+ # sync-claude-config.mjs
2
+
3
+ ## Огляд
4
+
5
+ Цей файл синхронізує конфігурацію Claude Code з шаблонів пакету `npm/.claude-template`, включаючи налаштування, slash-команди та хуки. Він забезпечує узгодженість між проєктом та базовою конфігурацією, автоматично оновлюючи та підтримуючи налаштування хуків та команд. Це дозволяє використовувати стандартні налаштування та автоматично адаптувати проєкт до змін у шаблоні.
6
+
7
+ ## Поведінка
8
+
9
+ - `parseGitignoreFragmentLines`: Розбиває рядок фрагменту `.gitignore` на окремі рядки, видаляє порожні та коментарні рядки.
10
+ - `syncGitignoreAdrFragment`: Дописує відсутні рядки з канонічного фрагменту `.gitignore` у `.gitignore` проєкту.
11
+ - `syncClaudeCommands`: Копіює slash-команди з `commands/` темплейту в `.claude/commands/*.md`.
12
+ - `syncClaudeSettings`: Об'єднує конфігурацію Claude Code з темплейту, зберігаючи користувацькі налаштування та перезаписуючи хуки, що ідентифікуються маркерами.
13
+ - `syncCursorHooksConfig`: Об'єднує конфігурацію хуків Cursor з темплейту, додаючи або видаляючи хуки ADR Stop-hook залежно від наявності правила `adr`.
14
+ - `syncAdrHookScript`: Копіює bash-скрипт ADR capture Stop-hook з темплейту в `.claude/hooks/capture-decisions.sh`.
15
+ - `syncAdrNormalizeHookScript`: Копіює bash-скрипт ADR normalize Stop-hook з темплейту в `.claude/hooks/normalize-decisions.sh`.
16
+ - `syncAdrHookLibScripts`: Копіює bash-скрипти lib-файлів з `commands/` темплейту в `.claude/hooks/lib/`.
17
+ - `removeOrphanAdrHookLib`: Видаляє директорію lib-файлів з `.claude/hooks/lib/`, якщо правило `adr` вимкнено.
18
+ - `syncPiExtensions`: Копіює розширення TypeScript з `npm/.pi-template/extensions/n-cursor-adr/` в `.pi/extensions/n-cursor-adr/`.
19
+ - `removeOrphanPiExtension`: Видаляє директорію розширення TypeScript з `.pi/extensions/n-cursor-adr/`, якщо правило `adr` вимкнено.
20
+ - `syncClaudeConfig`: Синхронізує конфігурацію Claude Code та Cursor hooks, об'єднуючи їх та додаючи/видаляючи хуки
21
+
22
+ ## Публічний API
23
+
24
+ - MANAGED_HOOK_COMMAND_MARKER — Маркер для фіксації хуків PostToolUse.
25
+ - LEGACY_STOP_HOOK_COMMAND_MARKER — Маркер для legacy-хуків Stop, використовується під час оновлення.
26
+ - ADR_HOOK_COMMAND_MARKER — Маркер для хуків ADR Stop, визначає шлях до скрипту capture-decisions.
27
+ - ADR_NORMALIZE_HOOK_COMMAND_MARKER — Маркер для хуків ADR Stop, визначає шлях до скрипту normalize-decisions.
28
+ - CURSOR_ADR_HOOK_COMMAND_MARKER — Маркер для хуків Cursor ADR Stop, шлях до скрипту в `.cursor/hooks.json`.
29
+ - CURSOR_ADR_NORMALIZE_HOOK_COMMAND_MARKER — Маркер для хуків Cursor ADR Normalize Stop, шлях до скрипту в `.cursor/hooks.json`.
30
+ - MANAGED_HOOK_COMMAND_MARKERS — Усі маркери managed-хуків пакета.
31
+ - PI_DIR — Корінь артефактів pi.dev у проєкті-споживачі.
32
+ - PI_EXTENSIONS_DIR — Директорія pi.dev TS-extensions у проєкті-споживачі.
33
+ - PI_TEMPLATE_DIR_NAME — Назва bundled-директорії pi-template у пакеті `@nitra/cursor`.
34
+ - PI_EXTENSION_NAME — Ім'
35
+
36
+ ## Гарантії поведінки
37
+
38
+ Немає кешування.
39
+
40
+ Функція повертає `true`, якщо синхронізація завершилася успішно.
41
+
42
+ Якщо `claude-config` встановлено на `false` у `.n-cursor.json`, функція не змінює конфігурацію Claude.
43
+
44
+ `settings.json` оновлюється шляхом об'єднання конфігурації з `.claude-template/settings.json`, де перекриваються команди, що містять `MANAGED_HOOK_COMMAND_MARKER`, дозволи `permissions.allow` об'єднуються, і правила `adr` додаються/видаляються згідно з їх статусом у `.n-cursor.json`.
45
+
46
+ `.claude/commands/*.md` оновлюється шляхом повного заміщення вмісту з `.claude-template/commands/`.
47
+
48
+ `.claude/hooks/capture-decisions.sh` оновлюється шляхом повного копіювання з `.claude-template/hooks/` лише тоді, коли правило `adr` увімкнено в `.n-cursor.json`.
49
+
50
+ `.claude/hooks/normalize-decisions.sh` оновлюється шляхом повного копіюювання з `.claude-template/hooks/` лише тоді, коли правило `adr` увімкнено в `.n-cursor.json`.
51
+
52
+ `.
@@ -0,0 +1,26 @@
1
+ # sync-setup-bun-deps-action.mjs
2
+
3
+ ## Огляд
4
+
5
+ Файл містить конфігурацію GitHub Action `setup-bun-deps`, яка автоматично встановлює залежності проєкту Bun. Він використовується workflow для підготовки середовища проєкту, забезпечуючи узгодженість та спрощуючи виконання тестів та інших завдань, що потребують Bun. Це дозволяє workflow, що використовує `actions/checkout@v6`, безпосередньо використовувати action, не потребуючи додаткової конфігурації.
6
+
7
+ ## Поведінка
8
+
9
+ 1. Перевіряє наявність шаблону composite action `action.yml` у каталозі `github-actions/setup-bun-deps/` всередині кореня пакету `@nitra/cursor`.
10
+ 2. Якщо шаблон не знайдено, кидає помилку, вказуючи очікуваний шлях та пропонуючи перевстановити пакет.
11
+ 3. Створює каталог `.github/actions/setup-bun-deps` у цільовому репозиторії, якщо його не існує.
12
+ 4. Зчитує вміст файлу `action.yml` з джерела.
13
+ 5. Записує вміст `action.yml` у файл `action.yml` у цільовому репозиторії. Додає новий рядок в кінці файлу, якщо потрібно.
14
+ 6. Повертає об'єкт, що містить інформацію про успішність запису та повний шлях до створеного файлу.
15
+
16
+ ## Публічний API
17
+
18
+ syncSetupBunDepsAction — Створює файл з залежностями Bun, використовуючи корінь пакета `@nitra/cursor`.
19
+
20
+ ## Гарантії поведінки
21
+
22
+ - Копіює файл `action.yml` з каталогу `github-actions/setup-bun-deps/` у каталог `.github/actions/setup-bun-deps/`.
23
+ - Забезпечує доступність action `setup-bun-deps` для workflow, що використовує `actions/checkout@v6`.
24
+ - Використовує `npx @nitra/cursor` для ініціалізації action.
25
+ - Не враховує наявність checkout runner.
26
+ - Не має кешування.