@nitra/cursor 3.27.0 → 3.29.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 +17 -0
  2. package/package.json +1 -3
  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/coverage-classify/index.mjs +60 -72
  63. package/scripts/coverage-fix.mjs +26 -23
  64. package/scripts/dispatcher/lib/subagent-runner.mjs +33 -102
  65. package/scripts/docs/coverage-fix-extract.md +32 -0
  66. package/scripts/docs/lint-cli.md +25 -0
  67. package/scripts/docs/post-tool-use-fix.md +27 -0
  68. package/scripts/docs/rename-yaml-extensions.md +36 -0
  69. package/scripts/docs/skills-cli.md +35 -0
  70. package/scripts/docs/sync-claude-config.md +52 -0
  71. package/scripts/docs/sync-setup-bun-deps-action.md +26 -0
  72. package/scripts/docs/upgrade-nitra-cursor-and-install.md +29 -0
  73. package/scripts/docs/worktree-cli.md +46 -0
  74. package/scripts/lib/docs/assert-project-root.md +28 -0
  75. package/scripts/lib/docs/diff-added-lines.md +34 -0
  76. package/scripts/lib/docs/read-n-cursor-config-lite.md +28 -0
  77. package/scripts/lib/docs/resolve-target-files.md +34 -0
  78. package/scripts/lib/docs/root-notice.md +28 -0
  79. package/scripts/lib/docs/rule-meta-helpers.md +34 -0
  80. package/scripts/lib/docs/rule-meta.md +34 -0
  81. package/scripts/lib/docs/rule-predicates.md +30 -0
  82. package/scripts/lib/docs/run-conftest-batch.md +26 -0
  83. package/scripts/lib/docs/run-lint-step.md +25 -0
  84. package/scripts/lib/docs/run-rule-cli.md +27 -0
  85. package/scripts/lib/docs/run-rule.md +32 -0
  86. package/scripts/lib/docs/run-standard-lint.md +22 -0
  87. package/scripts/lib/docs/run-standard-rule.md +24 -0
  88. package/scripts/lib/docs/skill-meta.md +31 -0
  89. package/scripts/lib/docs/sync-gitignore-worktree.md +31 -0
  90. package/scripts/lib/docs/template.md +40 -0
  91. package/scripts/lib/docs/timing-summary.md +24 -0
  92. package/scripts/lib/docs/workspaces.md +30 -0
  93. package/scripts/lib/docs/worktree-notice.md +27 -0
  94. package/scripts/lib/docs/worktree.md +38 -0
  95. package/scripts/utils/docs/ast-scan-utils.md +50 -0
  96. package/scripts/utils/docs/ensure-gitignore-entries.md +28 -0
  97. package/scripts/utils/docs/find-package-json-paths.md +26 -0
  98. package/scripts/utils/docs/lock-cache-dir.md +25 -0
  99. package/scripts/utils/docs/pass.md +25 -0
  100. package/scripts/utils/docs/resolve-cargo-manifest.md +23 -0
  101. package/scripts/utils/docs/resolve-cmd.md +29 -0
  102. package/scripts/utils/docs/resolve-js-root.md +25 -0
  103. package/scripts/utils/docs/test-helpers.md +36 -0
  104. package/scripts/utils/docs/walk-cache.md +27 -0
  105. package/scripts/utils/docs/walkDir.md +32 -0
  106. package/scripts/utils/docs/with-lock.md +25 -0
  107. package/scripts/utils/docs/worktree-fingerprint.md +27 -0
  108. package/skills/docgen/js/docgen-batch.mjs +95 -0
  109. package/skills/docgen/js/docgen-extract.mjs +33 -18
  110. package/skills/docgen/js/docgen-gen.mjs +140 -154
  111. package/skills/docgen/js/docgen-ignore.mjs +1 -6
  112. package/skills/docgen/js/docgen-prompts.mjs +33 -22
  113. package/skills/docgen/js/docgen-scan.mjs +1 -8
  114. package/skills/docgen/js/docs/docgen-extract.md +28 -0
  115. package/skills/docgen/js/docs/docgen-gen.md +41 -0
  116. package/skills/docgen/js/docs/docgen-ignore.md +24 -0
  117. package/skills/docgen/js/docs/docgen-prompts.md +24 -0
  118. package/skills/docgen/js/docs/docgen-scan.md +48 -0
  119. package/skills/fix/js/docs/llm-worker.md +27 -0
  120. package/skills/fix/js/docs/orchestrator.md +32 -0
  121. package/skills/fix/js/docs/t0.md +29 -0
  122. package/skills/fix/js/llm-worker.mjs +64 -29
  123. package/skills/fix/js/orchestrator.mjs +45 -54
  124. package/skills/fix/js/t0.mjs +16 -32
  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,122 +1,53 @@
1
1
  /**
2
- * SubagentRunner (spec §15.1) абстракція спавну сфокусованого субагента для
3
- * Активного Раннера (Ф3/Ф4). Backend обирається за доступністю:
4
- * 1. `claude-agent-sdk` (програмний, потребує `ANTHROPIC_API_KEY`);
5
- * 2. `claude -p` (CLI-auth користувача);
6
- * 3. `cursor-agent -p` (CLI-auth).
7
- * Нема жодного → throw (polyfill без runner-а не стартує, §2.2).
2
+ * SubagentRunner — спавн субагента через pi (провайдер-нейтрально).
3
+ * Модель обирається через resolveModel('avg') (каскад local→cloud) або через deps.model.
8
4
  *
9
- * pi.dev для inner-спавну НЕ використовується: у автономному режимі pi.dev —
10
- * зовнішній драйвер, тож спавн ним внутрішніх субагентів = рекурсія (§9.1).
5
+ * Контракт runner-а: { backend: 'pi', runStep(prompt, { cwd }) Promise<{ ok, output }> }.
6
+ * Усі callers (planner, executor, plan-panel, review, budget) використовують саме цей контракт.
11
7
  *
12
- * Усі probe-залежності (`spawn`/`isInPath`/`canImportSdk`/`query`) ін'єктуються,
13
- * щоб тестувати без реальних процесів і без SDK.
8
+ * pi НЕ спавниться рекурсивно коли pi — зовнішній драйвер (§9.1).
9
+ * У цьому проєкті зовнішній драйвер Claude Code; pi як субагент — безпечно.
14
10
  */
15
11
  import { spawnSync } from 'node:child_process'
16
- import { env as processEnv } from 'node:process'
17
12
 
18
- const NO_BACKEND =
19
- 'SubagentRunner: ні claude-agent-sdk (з ANTHROPIC_API_KEY), ні `claude`/`cursor-agent` у PATH — ' +
20
- 'субагентів спавнити нічим. Встанови CLI-runner або задай ANTHROPIC_API_KEY.'
13
+ import { resolveModel } from '../../../lib/models.mjs'
21
14
 
22
15
  /**
23
- * Чи є бінарник у PATH (через `command -v`).
24
- * @param {string} name ім'я виконуваного
25
- * @param {typeof import('node:child_process').spawnSync} [spawn] ін'єкція для тестів
26
- * @returns {boolean} true, якщо знайдено
16
+ * Викликає pi і повертає { ok, output }.
17
+ * @param {string} prompt
18
+ * @param {string} model provider/model-id або '' для pi-дефолту
19
+ * @param {{ cwd?: string }} [opts]
20
+ * @returns {{ ok: boolean, output: string }}
27
21
  */
28
- export function isBinaryInPath(name, spawn = spawnSync) {
29
- const r = spawn('command', ['-v', name], { shell: true, encoding: 'utf8' })
30
- return (r.status ?? 1) === 0
22
+ function callPi(prompt, model, { cwd } = {}) {
23
+ const modelArgs = model ? ['--model', model] : []
24
+ const r = spawnSync('pi', ['-p', prompt, ...modelArgs, '--no-session'], {
25
+ cwd,
26
+ encoding: 'utf8',
27
+ timeout: 600_000
28
+ })
29
+ const ok = !r.error && r.status === 0
30
+ const output = (r.stdout ?? '') + (r.error ? r.error.message : !ok ? (r.stderr ?? '') : '')
31
+ return { ok, output }
31
32
  }
32
33
 
33
34
  /**
34
- * Обирає backend субагентів за пріоритетом sdk > claude > cursor.
35
- * @param {{ hasApiKey: boolean, canImportSdk: boolean, isInPath: (name: string) => boolean }} probes доступність
36
- * @returns {'sdk' | 'claude' | 'cursor' | null} backend або null
35
+ * Створює pi-runner. Повертає { backend: 'pi', runStep }.
36
+ * @param {{ model?: string, callPi?: Function }} [deps] ін'єкції для тестів
37
+ * @returns {Promise<{ backend: string, runStep: (prompt: string, opts?: object) => Promise<{ ok: boolean, output: string }> }>}
37
38
  */
38
- export function selectBackend({ hasApiKey, canImportSdk, isInPath }) {
39
- if (hasApiKey && canImportSdk) return 'sdk'
40
- if (isInPath('claude')) return 'claude'
41
- if (isInPath('cursor-agent')) return 'cursor'
42
- return null
43
- }
44
-
45
- /**
46
- * CLI-runner (`claude -p` / `cursor-agent -p`) — CLI-auth, без API key.
47
- * @param {'claude' | 'cursor-agent'} bin виконуваний
48
- * @param {{ spawn?: typeof import('node:child_process').spawnSync }} [deps] ін'єкція
49
- * @returns {{ backend: string, runStep: (prompt: string, opts?: { cwd?: string }) => { ok: boolean, output: string } }} runner
50
- */
51
- export function cliRunner(bin, deps = {}) {
52
- const spawn = deps.spawn ?? spawnSync
53
- return {
54
- backend: bin,
55
- runStep(prompt, { cwd } = {}) {
56
- const r = spawn(bin, ['-p'], { input: prompt, cwd, encoding: 'utf8' })
57
- return { ok: (r.status ?? 1) === 0, output: `${r.stdout ?? ''}${r.stderr ?? ''}` }
58
- }
59
- }
60
- }
39
+ export async function createRunner(deps = {}) {
40
+ const model = deps.model ?? resolveModel('avg')
41
+ const callPiFn = deps.callPi ?? callPi
61
42
 
62
- /**
63
- * SDK-runner (`claude-agent-sdk`). `query` ін'єктується; за замовчуванням —
64
- * динамічний import (optional dependency).
65
- * @param {{ query?: (input: object) => object }} [deps] ін'єкція (query повертає async-iterable повідомлень)
66
- * @returns {{ backend: string, runStep: (prompt: string, opts?: { cwd?: string }) => Promise<{ ok: boolean, output: string }> }} runner
67
- */
68
- export function sdkRunner(deps = {}) {
69
43
  return {
70
- backend: 'sdk',
71
- async runStep(prompt, { cwd } = {}) {
72
- let query = deps.query
73
- if (!query) {
74
- const mod = await import('@anthropic-ai/claude-agent-sdk')
75
- query = mod.query
76
- }
77
- let output = ''
78
- let ok = true
44
+ backend: 'pi',
45
+ async runStep(prompt, opts = {}) {
79
46
  try {
80
- for await (const msg of query({
81
- prompt,
82
- options: { cwd, maxTurns: 20, allowedTools: ['Read', 'Edit', 'Bash'] }
83
- })) {
84
- if (typeof msg?.text === 'string') output += msg.text
85
- if (msg?.type === 'result') ok = msg.is_error !== true
86
- }
87
- } catch (error) {
88
- return { ok: false, output: String(error?.message ?? error) }
47
+ return callPiFn(prompt, model, opts)
48
+ } catch (e) {
49
+ return { ok: false, output: String(e?.message ?? e) }
89
50
  }
90
- return { ok, output }
91
51
  }
92
52
  }
93
53
  }
94
-
95
- /**
96
- * Створює runner за доступним backend-ом. `backend`/probe-и можна задати явно
97
- * (тести); інакше визначаються з env/PATH/SDK.
98
- * @param {{ backend?: string, env?: Record<string, string | undefined>, isInPath?: (name: string) => boolean, canImportSdk?: boolean, spawn?: (cmd: string, args: string[], opts: object) => object, query?: (input: object) => object }} [deps] ін'єкції
99
- * @returns {Promise<{ backend: string, runStep: (prompt: string, opts?: object) => object }>} runner
100
- */
101
- export async function createRunner(deps = {}) {
102
- const env = deps.env ?? processEnv
103
- const isInPath = deps.isInPath ?? (name => isBinaryInPath(name, deps.spawn))
104
- const canImportSdk = deps.canImportSdk ?? (await probeSdk())
105
- const backend = deps.backend ?? selectBackend({ hasApiKey: Boolean(env.ANTHROPIC_API_KEY), canImportSdk, isInPath })
106
- if (!backend) throw new Error(NO_BACKEND)
107
- if (backend === 'sdk') return sdkRunner(deps)
108
- return cliRunner(backend === 'claude' ? 'claude' : 'cursor-agent', deps)
109
- }
110
-
111
- /**
112
- * Чи імпортується `claude-agent-sdk` (optional dependency).
113
- * @returns {Promise<boolean>} true, якщо доступний
114
- */
115
- async function probeSdk() {
116
- try {
117
- await import('@anthropic-ai/claude-agent-sdk')
118
- return true
119
- } catch {
120
- return false
121
- }
122
- }
@@ -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
+ - Не має кешування.
@@ -0,0 +1,29 @@
1
+ # upgrade-nitra-cursor-and-install.mjs
2
+
3
+ ## Огляд
4
+
5
+ Файл автоматично синхронізує правила командного інтерфейсу (CLI) з останньою версією `@nitra/cursor` з npm registry. Це забезпечує, що локальна версія `@nitra/cursor` завжди актуальна, а також інсталює необхідні залежності за допомогою `bun i`. Він використовується для підтримки узгодженості між локальним проєктом та офіційним репозиторієм npm.
6
+
7
+ ## Поведінка
8
+
9
+ shouldSkipNpmVersionUpgrade: Визначає, чи потрібно оновлювати версію залежності з npm, враховуючи специфікатор залежності та різні типи специфікаторів (workspace, file, link тощо).
10
+ fetchLatestNitraCursorVersionFromNpm: Отримує останню версію пакета `@nitra/cursor` з npm registry та повертає її як рядок.
11
+ resolveInstalledPackageRoot: Повертає шлях до каталогу `node_modules/@nitra/cursor` якщо залежність встановлена, інакше повертає шлях до кореня пакету поточного процесу CLI (кеш npx).
12
+ upgradeNitraCursorToLatestAndBunInstall: Оновлює версію `@nitra/cursor` у `package.json` до останньої з npm, запускає `bun i` та повертає шлях до каталогу `node_modules/@nitra/cursor`.
13
+
14
+ ## Публічний API
15
+
16
+ - shouldSkipNpmVersionUpgrade — Перевіряє можливість оминання оновлення версії npm.
17
+ - fetchLatestNitraCursorVersionFromNpm — Отримує останню версію пакета `@nitra/cursor` з npm.
18
+ - resolveInstalledPackageRoot — Знаходить шлях до встановленого пакета.
19
+ - upgradeNitraCursorToLatestAndBunInstall — Оновлює `@nitra/cursor` до останньої версії та встановлює Bun.
20
+
21
+ ## Гарантії поведінки
22
+
23
+ - Якщо наявна залежність через `workspace:`, `file:`, `link:` – не змінює версію в npm registry та не запускає `bun i`.
24
+ - Запускає `bun i` у корені проєкту після підтягування останньої версії `@nitra/cursor` з npm registry.
25
+ - Повертає шлях до `node_modules/@nitra/cursor`, якщо каталог існує.
26
+ - В іншому випадку повертає шлях до кореня пакету поточного процесу CLI (наприклад, кеш npx).
27
+ - Не кидає винятки.
28
+ - У разі невдачі повертає `false` або `null`.
29
+ - Не використовує кешування.
@@ -0,0 +1,46 @@
1
+ # worktree-cli.mjs
2
+
3
+ ## Огляд
4
+
5
+ Файл `n-cursor worktree` є CLI-оркестратором для управління git worktree. Він дозволяє додавати, видаляти та перевіряти worktree, забезпечуючи зручний інтерфейс для роботи з декількома гілками в одному репозиторії. Цей інструмент використовується для організації робочого процесу розробника, що працює з кількома гілками.
6
+
7
+ ## Поведінка
8
+
9
+ 1. **Ініціалізація:** Отримує аргументи командного рядка, включаючи підкоманду та її параметри. Визначає поточний робочий каталог, якщо його не вказано. Ініціалізує контекст для логування та отримання дати.
10
+ 2. **Розбір підкоманди:** Визначає, яку підкоманду було передано. Залежно від підкоманди, виконує відповідні дії.
11
+ 3. **`add` (Створення нового worktree):**
12
+ - Перевіряє наявність необхідних параметрів: назви гілки та опису.
13
+ - Визначає унікальну назву гілки, якщо вона вже існує.
14
+ - Створює новий worktree, використовуючи вказану гілку та опис. Записує опис у файл `.md` у каталозі `.worktrees/`.
15
+ - Створює нагадування про незакомічені зміни основного дерева, якщо це необхідно.
16
+ 4. **`remove` (Видалення worktree):**
17
+ - Перевіряє наявність необхідного параметра: назви гілки.
18
+ - Видаляє checkout та файл `.md` для вказаної гілки.
19
+ - Видаляє всі осиротілі файли опису, які залишилися після видалення гілки.
20
+ - Очищає файли flow-sibling-ів (.flow.json/.events.jsonl/lock) для запобігання їх осиротіння.
21
+ 5. **`list` (Перелік worktree):**
22
+ - Виводить список всіх створених worktree, отриманий за допомогою команди `git worktree list`.
23
+ - Для кожного worktree виводить його повний шлях та вміст файлу опису `.md`.
24
+ 6. **`prune` (Видалення осиротілих worktree):**
25
+ - Визначає всі файли опису `.md`, які більше не пов'язані з жодною зареєстрованою гілкою worktree.
26
+ - Видаляє ці осиротілі файли опису.
27
+ 7. \*\*Викона
28
+
29
+ ## Публічний API
30
+
31
+ runWorktreeCli — Запускає підкоманду worktree.
32
+
33
+ ## Гарантії поведінки
34
+
35
+ - `runWorktreeCli` повертає `false` при будь-якій помилці.
36
+ - `runWorktreeCli` повертає `null` при помилці, якщо результат неможливо визначити.
37
+ - Немає кешування.
38
+ - `add <branch> "<опис>"` створює гілку `worktree` з описом.
39
+ - `remove <branch> [--force]` видаляє checkout гілки `worktree`, але не видаляє саму гілку.
40
+ - `list` виводить список всіх `worktree`.
41
+ - `prune` видаляє `worktree` без checkout.
42
+ - Немає гарантій щодо стану git-репозиторію.
43
+ - Немає гарантій щодо наявності незакомічених змін.
44
+ - Немає гарантій щодо наявності осиротілих `worktree`.
45
+ - `runWorktreeCli` не кидає винятків.
46
+ - Помилки переховуються.
@@ -0,0 +1,28 @@
1
+ # assert-project-root.mjs
2
+
3
+ ## Огляд
4
+
5
+ Файл забезпечує захист від непередбачуваної поведінки при запуску `npx @nitra/cursor` з піддиректорій git-репозиторію. Він гарантує, що процес синхронізації та встановлення артефактів виконується лише з кореневої директорії проєкту, запобігаючи розповсюдженню конфігураційних файлів у невідповідні місця. Це забезпечує узгодженість та передбачуваність процесу налаштування проєкту.
6
+
7
+ ## Поведінка
8
+
9
+ gitToplevel: Визначає реальний шлях кореня git-репозиторію, використовуючи `git rev-parse --show-toplevel`. Повертає `null`, якщо `git` недоступний або не вдалося визначити корінь.
10
+ safeRealpath: Повертає реальний шлях вказаного каталогу, ігноруючи символічні посилання. Якщо шлях не існує, повертає вихідний шлях без змін.
11
+ assertCwdIsProjectRoot: Перевіряє, чи поточний робочий каталог є коренем git-репозиторію. Якщо так, функція не робить нічого. Якщо каталог знаходиться всередині git-репозиторію, але не є його коренем, викидає помилку, що інформує про необхідність перейти в корінь репозиторію.
12
+
13
+ ## Публічний API
14
+
15
+ - gitToplevel — Отримує реальний шлях кореня git-репозиторію, використовуючи `git rev-parse --show-toplevel`. Повертає шлях або `null`, якщо `dir` не є коренем репозиторію або `git` недоступний.
16
+ - assertCwdIsProjectRoot — Перевіряє, чи `dir` є коренем git-репозиторію. Якщо `dir` є піддиректорією репозиторію або знаходиться поза репозиторієм (без визначення `toplevel`), то функція пропускає операцію без помилки.
17
+
18
+ ## Гарантії поведінки
19
+
20
+ - При запуску `npx @nitra/cursor` з кореня будь-якого git-репозиторію, виконується синхронізація проєкту.
21
+ - При запуску `npx @nitra/cursor` з піддиректорії git-репозиторію, `cwd` встановлюється на корінь git-репозиторію.
22
+ - Синхронізація проєкту включає створення та запуск сценаріїв для `.cursor/rules/`, `.cursor/skills/`, `.claude/`, `AGENTS.md`, `CLAUDE.md`, `.n-cursor.json`, `.gitignore`.
23
+ - Синхронізація проєкту включає запуск `bun install`.
24
+ - При невдачі синхронізації повертається `false` або `null`.
25
+ - Немає кешування.
26
+ - Не перехоплює винятки.
27
+ - Функція `gitToplevel` забезпечує доступ до кореня git-репозиторію.
28
+ - Функція `assertCwdIsProjectRoot` перевіряє, чи поточний `cwd` є коренем git-репозиторію.
@@ -0,0 +1,34 @@
1
+ # diff-added-lines.mjs
2
+
3
+ ## Огляд
4
+
5
+ Файл визначає, чи є рядок коду новим (introduced) або вже існував у проєкті. Він використовується для класифікації результатів аналізу коду (lint-findings) на основі їхнього розташування відносно версії проєкту. Це допомагає розробникам розуміти, які зміни коду потребують негайної уваги.
6
+
7
+ ## Поведінка
8
+
9
+ ALL_LINES: мітка, що позначає всі рядки файлу, які були introduced.
10
+ parseAddedLines: парсить вивід `git diff` та повертає мапу, де ключ — ім'я файлу, а значення — множина номерів рядків, які були додані.
11
+ addedLinesByFile: визначає мапу доданих рядків для заданих файлів, використовуючи `git diff` та `git ls-files`.
12
+ isIntroducedLine: перевіряє, чи рядок у файлі є introduced, використовуючи мапу, створену `addedLinesByFile`.
13
+
14
+ ## Публічний API
15
+
16
+ - ALL_LINES — Вказує на новий, не відстежений файл, що містить усі рядки.
17
+ - parseAddedLines — Аналізує вивід команди `git diff --unified=0` для створення мапи доданих рядків у файлі.
18
+ - addedLinesByFile — Визначає додані рядки у файлах, порівнюючи їх з версією в HEAD, та класифікує їх як відстежені або не відстежені.
19
+ - isIntroducedLine — Перевіряє, чи рядок у файлі є новим, тобто доданим.
20
+
21
+ ## Гарантії поведінки
22
+
23
+ - `ALL_LINES` повертає список усіх рядків файлу.
24
+ - `ALL_LINES` повертає `false` якщо не вдалося парсити diff.
25
+ - `parseAddedLines` повертає список рядків, які були додані у diff.
26
+ - `parseAddedLines` повертає `false` якщо не вдалося парсити diff.
27
+ - `addedLinesByFile` повертає список рядків, які були додані у кожному файлі.
28
+ - `isIntroducedLine` визначає, чи є рядок доданим у diff.
29
+ - `isIntroducedLine` повертає `false` якщо рядок не був доданий у diff.
30
+ - Результати парсингу кешуються для кожного запуску.
31
+ - Рядок вважається "introduced" якщо він є в diff.
32
+ - Рядок вважається "pre-existing" якщо він не є в diff.
33
+ - Рядки, що не були знайдені в diff, вважаються "untracked".
34
+ - `ALL_LINES` повертає всі рядки з diff, навіть якщо вони "untracked".
@@ -0,0 +1,28 @@
1
+ # read-n-cursor-config-lite.mjs
2
+
3
+ ## Огляд
4
+
5
+ Цей файл читає файл `.n-cursor.json`, що містить список правил для конфігурації. Він повертає цей список, щоб `fix.mjs` міг використовувати правила для визначення конфігурації. Це забезпечує базове читання конфігурації правил для запуску `fix.mjs` з командного рядка.
6
+
7
+ ## Поведінка
8
+
9
+ **readNCursorConfigLite**
10
+ Зчитує конфігурацію з файлу `.n-cursor.json`. Повертає об'єкт з інформацією про правила та вимкнені правила. Якщо файл відсутній, повертає конфігурацію з порожнім масивом правил.
11
+
12
+ **isRuleEnabled**
13
+ Перевіряє, чи правило з активним статусом згідно з конфігурацією. Повертає `true`, якщо файл відсутній, правило вимкнено в `disable-rules` або присутнє в `rules`. Повертає `false` в іншому випадку.
14
+
15
+ ## Публічний API
16
+
17
+ - readNCursorConfigLite — Завантажує конфігурацію курсора.
18
+ - isRuleEnabled — Перевіряє статус активності правила.
19
+
20
+ ## Гарантії поведінки
21
+
22
+ - Якщо файл `.n-cursor.json` відсутній, вважається, що всі правила включені.
23
+ - Якщо файл `.n-cursor.json` існує, але поле `rules` порожнє, вважається, що всі правила включені.
24
+ - Якщо файл `.n-cursor.json` існує і має поле `rules`, але поле `rules` порожнє, вважається, що всі правила включені.
25
+ - Якщо правило вказане в полі `disable-rules`, воно вимкнено.
26
+ - Повертає `false` якщо файл `.n-cursor.json` відсутній або недійсний.
27
+ - Повертає `null` якщо не вдалося прочитати файл `.n-cursor.json`.
28
+ - Не використовує кешування.