@7n/rules 1.43.1 → 1.44.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (75) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/docs/vitest.config.md +14 -19
  3. package/package.json +1 -1
  4. package/rules/abie/lib/docs/index.md +0 -2
  5. package/rules/abie/lib/http-route.mjs +1 -0
  6. package/rules/abie/lib/yaml.mjs +2 -0
  7. package/rules/ci4/marksman_config/docs/index.md +10 -0
  8. package/rules/ci4/marksman_config/main.mjs +2 -0
  9. package/rules/doc-files/docgen-prompts/docs/index.md +9 -0
  10. package/rules/doc-files/docgen-prompts/main.mjs +5 -0
  11. package/rules/hasura/internal_urls/docs/index.md +0 -2
  12. package/rules/hasura/internal_urls/docs/main.md +27 -15
  13. package/rules/hasura/internal_urls/main.mjs +1 -0
  14. package/rules/image-avif/avif_generation/docs/index.md +10 -0
  15. package/rules/image-avif/avif_generation/main.mjs +2 -0
  16. package/rules/rego/vscode_settings/docs/fix-vscode_settings.md +12 -10
  17. package/rules/rego/vscode_settings/fix-vscode_settings.mjs +5 -0
  18. package/rules/tauri/cargo_mutants_config/docs/index.md +0 -2
  19. package/rules/tauri/cargo_mutants_config/docs/main.md +38 -12
  20. package/rules/tauri/cargo_mutants_config/main.mjs +5 -1
  21. package/rules/tauri/core_test_isolation/docs/main.md +19 -16
  22. package/rules/tauri/core_test_isolation/main.mjs +3 -1
  23. package/rules/tauri/linux_deps/docs/main.md +25 -18
  24. package/rules/tauri/linux_deps/main.mjs +2 -1
  25. package/rules/tauri/release/docs/main.md +20 -12
  26. package/rules/tauri/release/main.mjs +2 -0
  27. package/rules/tauri/updater/docs/main.md +31 -14
  28. package/rules/tauri/updater/main.mjs +4 -0
  29. package/rules/test/coverage/concern.json +9 -0
  30. package/rules/test/coverage/fix-worker.mjs +111 -0
  31. package/rules/test/coverage/lib/classify/apply.mjs +67 -0
  32. package/rules/test/coverage/lib/classify/cache.mjs +77 -0
  33. package/rules/test/coverage/lib/classify/docs/apply.md +28 -0
  34. package/rules/test/coverage/lib/classify/docs/cache.md +34 -0
  35. package/rules/test/coverage/lib/classify/docs/index.md +37 -0
  36. package/rules/test/coverage/lib/classify/docs/prompt.md +30 -0
  37. package/rules/test/coverage/lib/classify/docs/verdict-schema.md +30 -0
  38. package/rules/test/coverage/lib/classify/index.mjs +140 -0
  39. package/rules/test/coverage/lib/classify/prompt.mjs +136 -0
  40. package/rules/test/coverage/lib/classify/verdict-schema.mjs +163 -0
  41. package/rules/test/coverage/lib/llm.mjs +100 -0
  42. package/rules/test/coverage/main.mjs +161 -0
  43. package/rules/test/main.json +1 -0
  44. package/rules/test/main.mdc +140 -0
  45. package/rules/test/package_json/concern.json +11 -0
  46. package/rules/test/package_json/package_json.mdc +18 -0
  47. package/rules/test/package_json/package_json.rego +25 -0
  48. package/rules/test/package_json/template/package.json.contains.json +6 -0
  49. package/rules/text/oxfmtrc/fix-oxfmtrc.mjs +5 -0
  50. package/rules/text/vscode_settings/fix-vscode_settings.mjs +5 -0
  51. package/rules/worktree/vscode_settings/docs/fix-vscode_settings.md +10 -7
  52. package/rules/worktree/vscode_settings/fix-vscode_settings.mjs +5 -0
  53. package/rules/worktree/zed_settings/fix-zed_settings.mjs +5 -0
  54. package/schemas/n-rules.json +18 -1
  55. package/scripts/lib/adr/docs/index.md +0 -2
  56. package/scripts/lib/adr/docs/normalize-pipeline.md +44 -28
  57. package/scripts/lib/adr/normalize-pipeline.mjs +11 -0
  58. package/scripts/lib/auto-worktree.mjs +9 -3
  59. package/scripts/lib/docs/auto-worktree.md +50 -12
  60. package/scripts/lib/docs/inline-template-links.md +17 -8
  61. package/scripts/lib/docs/plugin-api.md +1 -1
  62. package/scripts/lib/docs/worktree-notice.md +65 -10
  63. package/scripts/lib/inline-template-links.mjs +5 -0
  64. package/scripts/lib/lint-surface/docs/run-detectors.md +25 -22
  65. package/scripts/lib/lint-surface/docs/tier-sampling-experiment.md +30 -14
  66. package/scripts/lib/lint-surface/run-detectors.mjs +1 -1
  67. package/scripts/lib/lint-surface/tier-sampling-experiment.mjs +1 -0
  68. package/scripts/lib/plugin-api.mjs +46 -0
  69. package/scripts/lib/worktree-notice.mjs +5 -3
  70. package/scripts/utils/docs/walkDir.md +26 -15
  71. package/scripts/utils/docs/worktree-fingerprint.md +16 -15
  72. package/scripts/utils/walkDir.mjs +9 -5
  73. package/scripts/utils/worktree-fingerprint.mjs +5 -0
  74. package/skills/storybook/SKILL.md +4 -4
  75. package/skills/taze/js/migration-cache.mjs +1 -1
@@ -78,6 +78,52 @@ export const PLUGIN_API_VERSION = 1
78
78
  const REQUIRED_PROVIDER_FUNCTIONS = ['detect', 'available', 'backup', 'bump', 'diff', 'promptFor', 'cleanup']
79
79
  const REQUIRED_PROVIDER_STRINGS = ['id', 'title', 'manifestNoun', 'skillSection']
80
80
 
81
+ /**
82
+ * @typedef {object} CoverageRow
83
+ * Агрегований вимір однієї області (`JS`, `Vue (Storybook)`, `Rust`, …).
84
+ * @property {string} area назва рядка звіту
85
+ * @property {{lines:{covered:number,total:number}, functions:{covered:number,total:number}}} coverage line/function coverage
86
+ * @property {{caught:number, total:number}} mutation вбиті/всі мутанти (0/0 — мутаційне тестування не вимірювалось)
87
+ * @property {Array<{file:string, mutants:Array<object>, exampleTest?:object|null, recommendationText?:string|null}>} survived вцілілі мутанти по файлах (шляхи relative до cwd)
88
+ */
89
+
90
+ /**
91
+ * @typedef {object} CoverageProvider
92
+ * Порт мовної екосистеми для концерну `coverage` правила `test` (spec
93
+ * 2026-07-22 absorb-7n-test). Ядро викликає: `detect` → повний вимір
94
+ * `collect` (full/`lint test`) АБО делта-вимір `collectPerFile` (делта-lint,
95
+ * без мутаційного тестування). Реєстрація — `contributes.handlers.coverage`
96
+ * у маніфесті плагіна, default-експорт handler-модуля.
97
+ * @property {string} id стабільний ідентифікатор екосистеми (напр. `js`)
98
+ * @property {string} title заголовок для звітів/повідомлень
99
+ * @property {(cwd: string) => Promise<boolean>} detect чи застосовний вимір у проєкті (false → тихий skip виміру)
100
+ * @property {(cwd: string, opts?: {changedFiles?: string[], base?: string|null, runner?: object}) => Promise<CoverageRow[]>} collect повний вимір: coverage + мутаційне тестування по всіх workspaces
101
+ * @property {(cwd: string, opts: {files: string[], runner?: object}) => Promise<Array<{file:string, pct:number, linesFound:number, linesCovered:number, reason?:string}>>} collectPerFile легкий делта-вимір per-file line coverage змінених файлів (без мутаційного тестування)
102
+ */
103
+
104
+ const REQUIRED_COVERAGE_FUNCTIONS = ['detect', 'collect', 'collectPerFile']
105
+ const REQUIRED_COVERAGE_STRINGS = ['id', 'title']
106
+
107
+ /**
108
+ * Валідує форму coverage-провайдера з модуля плагіна.
109
+ * @param {unknown} candidate default-експорт handler-модуля плагіна
110
+ * @param {string} source ім'я плагіна/шлях модуля для повідомлення
111
+ * @returns {CoverageProvider} той самий обʼєкт, якщо валідний
112
+ */
113
+ export function assertCoverageProvider(candidate, source) {
114
+ if (!candidate || typeof candidate !== 'object') {
115
+ throw new TypeError(`plugin-api: ${source} — default-експорт не є обʼєктом CoverageProvider`)
116
+ }
117
+ const missing = [
118
+ ...REQUIRED_COVERAGE_STRINGS.filter(k => typeof candidate[k] !== 'string' || candidate[k] === ''),
119
+ ...REQUIRED_COVERAGE_FUNCTIONS.filter(k => typeof candidate[k] !== 'function')
120
+ ]
121
+ if (missing.length > 0) {
122
+ throw new TypeError(`plugin-api: ${source} — CoverageProvider без обовʼязкових полів: ${missing.join(', ')}`)
123
+ }
124
+ return /** @type {CoverageProvider} */ (candidate)
125
+ }
126
+
81
127
  /**
82
128
  * Валідує форму провайдера з модуля плагіна — зрозуміла помилка замість
83
129
  * «undefined is not a function» глибоко в оркестраторі.
@@ -133,7 +133,9 @@ git branch --show-current
133
133
 
134
134
  **Root-assert.** Якщо \`pwd\` **не** збігається з виводом \`git rev-parse --show-toplevel\` — ти в **піддиректорії** робочого дерева (worktree-шляхи нижче відносні до кореня репо). Спершу перейди в корінь: \`cd <toplevel>\` (literal-шлях із виводу), і лише тоді продовжуй preflight. Не створюй worktree з піддиректорії — \`cd .worktrees/<…>\` звідти впаде.
135
135
 
136
- Якщо \`git rev-parse --show-toplevel\` показав, що ти **не** в \`.worktrees/\`, візьми вивід \`git branch --show-current\` як \`<current-branch>\` і виконай **literal-команди без shell expansion** (без command substitution, variable expansion чи backticks). Наприклад, якщо поточна гілка \`feature/x\`:
136
+ **Вже ізольований — нічого не створюй.** Якщо \`git rev-parse --show-toplevel\` містить сегмент \`.worktrees/<…>\` (репо-конвенція) **або** \`.claude/worktrees/<…>\` (worktree харнесу Claude Code — туди \`npx @7n/mt worktree create\` класти заборонено, \`n-worktree.mdc\`) ти вже виконуєшся в окремому git-worktree. Preflight пройдено: нічого не створюй, нікого не питай про назву гілки переходь одразу до Кроку 0.1.
137
+
138
+ Інакше, якщо toplevel не містить жодного з цих сегментів, візьми вивід \`git branch --show-current\` як \`<current-branch>\` і виконай **literal-команди без shell expansion** (без command substitution, variable expansion чи backticks). Наприклад, якщо поточна гілка \`feature/x\`:
137
139
 
138
140
  \`\`\`bash
139
141
  npx @7n/mt worktree create "feature/x-${suffix}" "n-${suffix}: worktree-only skill"
@@ -142,10 +144,10 @@ cd ".worktrees/feature-x-${suffix}"
142
144
 
143
145
  Тобто branch-argument лишає slash як у git-гілці, а шлях для \`cd\` бере sanitized форму: slash → \`-\`.
144
146
 
145
- **Крок 0.1 — bootstrap у новому дереві (після \`cd\`).** Дерево щойно створене й **без** \`node_modules\`. Постав залежності локально — тоді \`npx @7n/rules <cmd>\` бере локальну копію без походу в реєстр:
147
+ **Крок 0.1 — bootstrap (якщо в дереві ще нема \`node_modules\`).** Свіжостворений worktree (Крок 0) точно без \`node_modules\`; вже ізольований harness-worktree може мати їх або ні постав локально, тоді \`npx @7n/rules <cmd>\` бере локальну копію без походу в реєстр:
146
148
 
147
149
  \`\`\`bash
148
- bun install
150
+ test -d node_modules || bun install
149
151
  \`\`\``
150
152
  }
151
153
 
@@ -3,31 +3,42 @@ type: JS Module
3
3
  title: walkDir.mjs
4
4
  resource: npm/scripts/utils/walkDir.mjs
5
5
  docgen:
6
- crc: 6f26e08f
7
- model: omlx/gemma-4-e4b-it-OptiQ-4bit
6
+ crc: 1bbc24bc
7
+ model: openai-codex/gpt-5.5
8
+ tier: cloud-avg
8
9
  score: 100
10
+ judgeModel: openai-codex/gpt-5.4-mini
9
11
  ---
10
12
 
11
- Публічна функція `walkDir` здійснює рекурсивний пошук файлів у вказаному каталозі. Вона обходить файлову систему, ігноруючи каталоги `.git`, `node_modules` та worktree-чекаути (`.worktrees/`, `.claude/worktrees/` — повні копії репо від сесійних git-worktree Claude/агентів). Знаходячи кожен файл, вона передає його повний шлях у колбек для подальшої обробки. Компонент є read-only, тобто не виконує записів у файлову систему чи бази даних. При роботі з файловою системою він перехоплює помилки, забезпечуючи безпечну роботу без викидання винятків.
13
+ ## Огляд
14
+
15
+ Файл описує правила пропуску службових і агентських шляхів під час читання репозиторію. `WORKTREE_CHECKOUT_GLOBS` задає шаблони агентських worktree-копій, `ALWAYS_IGNORE` фіксує завжди ігноровані `.git` і `node_modules`.
16
+
17
+ `isWorktreeCheckoutPath` перевіряє вже відомий відносний шлях на належність до агентського worktree. `walkDir` виконує fail-safe обхід файлового дерева: перехоплює помилки читання і не передає винятки назовні.
12
18
 
13
19
  ## Поведінка
14
20
 
15
- 1. Викликається функція walkDir для початку рекурсивного обходу каталогу.
16
- 2. Система розшифровує вхідний шлях до кореня обходу.
17
- 3. Система формує додаткові правила ігнорування на основі наданих шляхів.
18
- 4. Система завжди ігнорує каталоги .git, node_modules і worktree-чекаути (.worktrees/, .claude/worktrees/) на будь-якій глибині.
19
- 5. Система виконує пошук усіх файлів у каталозі, застосовуючи правила ігнорування, включаючи ті, що визначені в .gitignore.
20
- 6. У разі виникнення помилки під час пошуку, процес обходу припиняється без генерації винятку.
21
- 7. Для кожного знайденого файлу система викликає наданий колбек, передаючи йому повний абсолютний шлях до цього файлу.
21
+ `WORKTREE_CHECKOUT_GLOBS` задає спільне правило безпеки для агентських worktree-копій, щоб обхід не сприймав дублікати репозиторію як робочий код.
22
+
23
+ `ALWAYS_IGNORE` розширює це правило постійними пропусками `.git` і `node_modules`; ці винятки застосовуються під час повного обходу незалежно від налаштувань репозиторію.
24
+
25
+ `walkDir` приймає корінь обходу, додає до спільних правил додаткові локальні винятки, читає файлове дерево з урахуванням `.gitignore` і передає знайдені файли далі як абсолютні шляхи. Якщо обхід неможливий, він завершується без помилки назовні, щоб перевірки залишались fail-safe.
26
+
27
+ `isWorktreeCheckoutPath` використовує те саме смислове правило пропуску worktree-чекаутів для уже наявних відносних шляхів, які не проходять через `walkDir`, наприклад зі списків git.
22
28
 
23
29
  ## Публічний API
24
30
 
25
- - walkDirрекурсивно переглядає файли та папки, ігноруючи ті, що вказані у файлі `.gitignore`.
26
- - isWorktreeCheckoutPath предикат для відносного posix-шляху: чи лежить він усередині worktree-чекаута (`.worktrees/` або `.claude/worktrees/`). Для фільтрації git-списків, що не проходять через walkDir (наприклад, delta-список змінених файлів).
27
- - ALWAYS_IGNORE, WORKTREE_CHECKOUT_GLOBS експортовані glob-константи безумовних пропусків обходу.
31
+ - WORKTREE_CHECKOUT_GLOBSСесійні git-worktree чекаути (Claude/агенти): повні копії репо, не робочий код.
32
+ Споживацькі репо часто не мають цих шляхів у .gitignore, тож без safety net
33
+ lint-обхід бачив би дубль усього дерева.
34
+ - ALWAYS_IGNORE — .git ніколи не потрапляє в .gitignore — пропускаємо завжди.
35
+ node_modules — safety net: проєкт може не мати .gitignore або запускатись поза git-репо.
36
+ - isWorktreeCheckoutPath — Чи лежить відносний posix-шлях усередині worktree-чекаута (`.worktrees/` або
37
+ `.claude/worktrees/`). Для фільтрації git-списків, що не проходять через walkDir.
38
+ - walkDir — Рекурсивно обходить каталог, поважаючи .gitignore (включно з вкладеними).
28
39
 
29
40
  ## Гарантії поведінки
30
41
 
31
- - Read-only: не виконує операцій запису (ФС/БД).
42
+ - Власних операцій запису (ФС/БД) у файлі немає; виклики імпортованих модулів можуть писати.
32
43
  - Перехоплює помилки і не пропускає винятків назовні (fail-safe).
33
- - Свідомо пропускає шляхи: `.git`, `node_modules`, `.worktrees/`, `.claude/worktrees/`.
44
+ - Свідомо пропускає шляхи: `.git`, `node_modules`.
@@ -3,29 +3,30 @@ type: JS Module
3
3
  title: worktree-fingerprint.mjs
4
4
  resource: npm/scripts/utils/worktree-fingerprint.mjs
5
5
  docgen:
6
- crc: df297382
6
+ crc: 38831a93
7
+ model: openai-codex/gpt-5.4-mini
8
+ tier: cloud-min
9
+ score: 100
10
+ judgeModel: openai-codex/gpt-5.4-mini
7
11
  ---
8
12
 
9
- Файл надає унікальний відбиток робочої директорії. Цей відбиток використовується для ідентифікації та порівняння робочих директорій, забезпечуючи їх унікальність у системі. Він слугує базовим інструментом для відстеження та управління версіями.
13
+ ## Огляд
14
+
15
+ `worktreeFingerprint` формує стабільний fingerprint git-робочого дерева з `HEAD`, diff і `untracked`-файлів. Це потрібно, щоб розпізнавати той самий стан дерева й дедуплікувати повторні `lint --full` прогони без змін.
10
16
 
11
17
  ## Поведінка
12
18
 
13
- 1. Отримує поточний SHA256 хеш коміту, який знаходиться в гілці HEAD.
14
- 2. Отримує текст зміни між комітом HEAD та робочим каталогом.
15
- 3. Отримує список не відстежених файлів у робочому каталозі, не включаючи стандартні файли, що ігноруються.
16
- 4. Для кожного не відстеженого файлу отримує його SHA256 хеш.
17
- 5. Об'єднує SHA256 хеш коміту, текст зміни та пари "файл:хеш" не відстежених файлів, розділяючи їх новими рядками.
18
- 6. Обчислює SHA256 хеш отриманого текстового рядка.
19
- 7. Повертає отриманий SHA256 хеш у форматі 64-значної шестнадцяткової строки.
20
- 8. Якщо виникає помилка під час виконання будь-якої з операцій, повертає `null`.
19
+ 1. worktreeFingerprint визначає, чи поточне git-робоче дерево вже має унікальний стан для повторного повного lint-прогону.
20
+ 2. Якщо дерево не належить git-репо або перевірку неможливо виконати, повертає `null`.
21
+ 3. Інакше бере базовий стан з `HEAD`, додає різницю від `HEAD` і враховує всі untracked-файли, щоб зміна вмісту або набору нових файлів впливала на результат.
22
+ 4. Для untracked-файлів формує впорядковану сукупність «шлях + вміст», щоб однаковий набір файлів давав той самий fingerprint незалежно від порядку їх виявлення.
23
+ 5. На основі цього зводить весь стан дерева в один SHA-256 fingerprint у вигляді hex-рядка.
24
+ 6. Використовується як стабільний маркер незміненого дерева для відсікання повторних повних lint-прогонів.
21
25
 
22
26
  ## Публічний API
23
27
 
24
- worktreeFingerprint — генерує унікальний відбиток поточного стану репозиторію Git.
28
+ - worktreeFingerprint — Fingerprint поточного стану git-робочого дерева.
25
29
 
26
30
  ## Гарантії поведінки
27
31
 
28
- - Функція повертає `true`, якщо відбиток дерева робіт успішно обчислено.
29
- - Функція повертає `null`, якщо обчислення відбитка дерева робіт не вдалося.
30
- - Функція не викликає винятків.
31
- - Функція не використовує кеш.
32
+ - (специфічних машинно-виведених гарантій немає)
@@ -2,13 +2,17 @@
2
2
  import { join, relative, resolve, sep } from 'node:path'
3
3
  import { globby } from 'globby'
4
4
 
5
- // Сесійні git-worktree чекаути (Claude/агенти): повні копії репо, не робочий код.
6
- // Споживацькі репо часто не мають цих шляхів у .gitignore, тож без safety net
7
- // lint-обхід бачив би дубль усього дерева.
5
+ /**
6
+ * Сесійні git-worktree чекаути (Claude/агенти): повні копії репо, не робочий код.
7
+ * Споживацькі репо часто не мають цих шляхів у .gitignore, тож без safety net
8
+ * lint-обхід бачив би дубль усього дерева.
9
+ */
8
10
  export const WORKTREE_CHECKOUT_GLOBS = ['**/.worktrees/**', '**/.claude/worktrees/**']
9
11
 
10
- // .git ніколи не потрапляє в .gitignore — пропускаємо завжди.
11
- // node_modules safety net: проєкт може не мати .gitignore або запускатись поза git-репо.
12
+ /**
13
+ * .git ніколи не потрапляє в .gitignore пропускаємо завжди.
14
+ * node_modules — safety net: проєкт може не мати .gitignore або запускатись поза git-репо.
15
+ */
12
16
  export const ALWAYS_IGNORE = ['.git/**', 'node_modules/**', ...WORKTREE_CHECKOUT_GLOBS]
13
17
 
14
18
  const WORKTREE_CHECKOUT_RE = /(?:^|\/)(?:\.worktrees|\.claude\/worktrees)\//u
@@ -1,3 +1,8 @@
1
+ /**
2
+ * Fingerprint git-робочого дерева (HEAD + diff + untracked-файли) —
3
+ * використовується для дедуплікації повторних lint --full прогонів на
4
+ * незміненому дереві.
5
+ */
1
6
  import { spawnSync } from 'node:child_process'
2
7
  import { createHash } from 'node:crypto'
3
8
 
@@ -12,7 +12,7 @@ version: '1.0'
12
12
 
13
13
  Джерело рішення: `docs/adr/канон-storybook-для-vue-компонентних-бібліотек.md`. Уся логіка канону
14
14
  (скоуп, скафолд, vitest-конфіг, гігієна залежностей, adopt-діагностика) живе в правилі `storybook`
15
- пакета `@7n/rules-lang-js` (`node_modules/@7n/rules-lang-js/rules/storybook/`) — цей скіл лише
15
+ пакета `@7n/rules-lang-js` (`node_modules/@7n/rules-lang-js/rules/test/`) — цей скіл лише
16
16
  тонка обгортка запуску, за зразком `doc-files`.
17
17
 
18
18
  ## Передумови
@@ -50,14 +50,14 @@ npx @7n/rules lint storybook
50
50
 
51
51
  ```bash
52
52
  # Діагностика всіх пакетів у скоупі (без запису)
53
- bun node_modules/@7n/rules-lang-js/rules/storybook/adopt/main.mjs
53
+ bun node_modules/@7n/rules-lang-js/rules/test/storybook-adopt/main.mjs
54
54
 
55
55
  # + генерація повністю відсутніх секцій (main.js/preview.js/mocks/scripts/vitest-конфіги
56
56
  # лишаються недоторканими, якщо вже існують хоч у якомусь вигляді)
57
- bun node_modules/@7n/rules-lang-js/rules/storybook/adopt/main.mjs --fix-missing
57
+ bun node_modules/@7n/rules-lang-js/rules/test/storybook-adopt/main.mjs --fix-missing
58
58
 
59
59
  # Звузити діагностику до конкретних пакетів (root dir, той самий формат що storybook.optOut)
60
- bun node_modules/@7n/rules-lang-js/rules/storybook/adopt/main.mjs --fix-missing packages/ui packages/legacy-ui
60
+ bun node_modules/@7n/rules-lang-js/rules/test/storybook-adopt/main.mjs --fix-missing packages/ui packages/legacy-ui
61
61
  ```
62
62
 
63
63
  Прогін через прямий виклик скрипта плагіна (`node_modules/@7n/rules-lang-js/...`) — CLI-плюмбінг
@@ -69,7 +69,7 @@ export async function writeMigrationCache(pkg, from, to, entry, deps = {}) {
69
69
 
70
70
  /**
71
71
  * Дописує до промпта `provider.promptFor(entry)` підсумок відомої міграції,
72
- * якщо кеш її знайшов — каже раннеру пропустити крок 1 (CHANGELOG/diff-
72
+ * якщо кеш її знайшов — каже runner-у пропустити крок 1 (CHANGELOG/diff-
73
73
  * дослідження) і одразу шукати використання в поточному проєкті.
74
74
  * @param {string} prompt базовий промпт з `provider.promptFor(entry)`
75
75
  * @param {{notes: string, sourceRepo: string}} cached кешований запис