@nitra/cursor 12.8.5 → 12.8.6

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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # Changelog
2
2
 
3
+ ## [12.8.6] - 2026-06-22
4
+
5
+ ### Changed
6
+
7
+ - ✨ feat(rules/abie): http_route_base.mdc + активація + ua-домени у ua_http_route.mdc
8
+
3
9
  ## [12.8.5] - 2026-06-22
4
10
 
5
11
  ### Changed
package/bin/n-cursor.js CHANGED
@@ -630,16 +630,16 @@ function buildClaudeLintParallelismSectionLines() {
630
630
  }
631
631
 
632
632
  /**
633
- * Рендерить секцію для CLAUDE.md: скіли з `meta.json.worktree === true` запускаються
633
+ * Рендерить секцію для CLAUDE.md: скіли з `main.json.worktree === true` запускаються
634
634
  * лише в окремому git-worktree (дублює fail-fast банер `SKILL.md` як завжди-читане правило).
635
635
  * @returns {string[]} рядки для вставки (з порожнім рядком на початку)
636
636
  */
637
637
  function buildClaudeWorktreeEnforcementSectionLines() {
638
638
  return [
639
639
  '',
640
- '## Worktree-only skills (`meta.json` → `worktree: true`)',
640
+ '## Worktree-only skills (`main.json` → `worktree: true`)',
641
641
  '',
642
- 'Скіл із **`worktree: true`** у `meta.json` запускається **виключно** в окремому git-worktree (`.worktrees/<current-branch>-<suffix>/`) — **не** в основному дереві й **не** паралельно. Перший крок такого скіла (блок `n-cursor:worktree:start` у його `SKILL.md`) — **preflight**: якщо `git rev-parse --show-toplevel` не вказує під `.worktrees/`, **STOP** і не питай користувача про назву гілки; створи worktree від поточної гілки готовим snippet з `SKILL.md` за конвенцією `<current-branch>-<suffix>` і без shell expansion (без command substitution, variable expansion чи backticks). Чисте робоче дерево — **не** привід пропустити preflight.',
642
+ 'Скіл із **`worktree: true`** у `main.json` запускається **виключно** в окремому git-worktree (`.worktrees/<current-branch>-<suffix>/`) — **не** в основному дереві й **не** паралельно. Перший крок такого скіла (блок `n-cursor:worktree:start` у його `SKILL.md`) — **preflight**: якщо `git rev-parse --show-toplevel` не вказує під `.worktrees/`, **STOP** і не питай користувача про назву гілки; створи worktree від поточної гілки готовим snippet з `SKILL.md` за конвенцією `<current-branch>-<suffix>` і без shell expansion (без command substitution, variable expansion чи backticks). Чисте робоче дерево — **не** привід пропустити preflight.',
643
643
  ''
644
644
  ]
645
645
  }
@@ -795,10 +795,10 @@ async function syncSkills(configSkills, bundledSkillsDir = BUNDLED_SKILLS_DIR) {
795
795
  const rootOnly = !worktree && meta?.requireRoot === true
796
796
  const entries = await readdir(srcDir, { withFileTypes: true })
797
797
  for (const entry of entries) {
798
- // Лише top-level файли скіла. `meta.json` — метадані (не для споживача);
798
+ // Лише top-level файли скіла. `main.json` — метадані (не для споживача);
799
799
  // підкаталоги (`js/` — скіл-специфічний код) виконуються з пакета через
800
800
  // `npx`, у проєкт не копіюються (як `npm/rules/<id>/js/`). Див. scripts.mdc.
801
- if (!entry.isFile() || entry.name === 'meta.json') continue
801
+ if (!entry.isFile() || entry.name === 'main.json') continue
802
802
  let content = await readFile(join(srcDir, entry.name), 'utf8')
803
803
  if (entry.name === 'SKILL.md') {
804
804
  content = injectWorktreeNotice(content, worktree)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nitra/cursor",
3
- "version": "12.8.5",
3
+ "version": "12.8.6",
4
4
  "description": "CLI для завантаження cursor-правил (префікс n-) у локальний репозиторій",
5
5
  "keywords": [
6
6
  "cli",
@@ -0,0 +1,25 @@
1
+ ## k8s: **HTTPRoute** у base-шарі — домени `aiml.live`
2
+
3
+ У **HTTPRoute** під шляхом **`…/k8s/.../base/...`** (сегмент `base` у path) усі значення **`spec.hostnames`** мають належати до домену **`aiml.live`**: точна відповідність **`aiml.live`**, wildcard **`*.aiml.live`** або будь-який піддомен (**`api.aiml.live`**, **`app.aiml.live`** тощо). Перевірка — case-insensitive.
4
+
5
+ Rego-пакет: **`abie.http_route_base`** (`policy/http_route_base/`). Цільові файли: `…/k8s/.../base/.../*.yaml` типу HTTPRoute.
6
+
7
+ ```yaml title="…/k8s/base/hr.yaml"
8
+ apiVersion: gateway.networking.k8s.io/v1
9
+ kind: HTTPRoute
10
+ metadata:
11
+ name: my-app
12
+ spec:
13
+ hostnames:
14
+ - "my-app.aiml.live" # ✓ піддомен aiml.live
15
+ parentRefs:
16
+ - name: gateway
17
+ ```
18
+
19
+ Недозволені в base-шарі (але коректні для ua-overlay — `abie.app`, `vybeerai.com.ua`):
20
+
21
+ ```yaml
22
+ hostnames:
23
+ - "abie.app" # ✗ ua-домен, не base
24
+ - "vybeerai.com.ua" # ✗ ua-домен, не base
25
+ ```
@@ -1,6 +1,6 @@
1
1
  ## k8s: overlay **HTTPRoute** (**ua**)
2
2
 
3
- За наявності **Deployment** під **k8s** і наявності **Vite** (**`vite.config.js`**, **`vite.config.mjs`** або **`vite.config.ts`** у каталозі пакета) у **`ua/kustomization.yaml`** цього пакета потрібні **inline JSON6902** у **`patches`**: **target** **`kind: HTTPRoute`**, **непорожній `name`** (як у маніфесті маршруту). Мають бути зміни **`/spec/hostnames`** (домени abie у скрипті) та **`/spec/parentRefs/0/namespace`** (**`ua`**, також дозволені префікси **`ua-*`**, наприклад **`ua-b2b`**). Як обирати **`op`** (**add** / **replace** тощо) у patch — **k8s.mdc** (розділ про JSON patch у kustomization).
3
+ За наявності **Deployment** під **k8s** і наявності **Vite** (**`vite.config.js`**, **`vite.config.mjs`** або **`vite.config.ts`** у каталозі пакета) у **`ua/kustomization.yaml`** цього пакета потрібні **inline JSON6902** у **`patches`**: **target** **`kind: HTTPRoute`**, **непорожній `name`** (як у маніфесті маршруту). Мають бути зміни **`/spec/hostnames`** (хоча б один з доменів: **`abie.app`**, **`vybeerai.com.ua`**, **`*.abie.app`**, **`*.vybeerai.com.ua`**) та **`/spec/parentRefs/0/namespace`** (**`ua`**, також дозволені префікси **`ua-*`**, наприклад **`ua-b2b`**). Як обирати **`op`** (**add** / **replace** тощо) у patch — **k8s.mdc** (розділ про JSON patch у kustomization).
4
4
 
5
5
  ### HTTPRoute: спільні сервіси **`auth-run-hl`**, **`file-link-hl`**
6
6
 
@@ -6,8 +6,20 @@ version: '1.22'
6
6
 
7
7
  Правило **abie** для споживачів **@nitra/cursor**: **k8s** (Deployment + **HealthCheckPolicy** у **`hc.yaml`**, overlay **ua** — **nodeSelector**, **HTTPRoute** (будь-який непорожній **`target.name`**, для спільних сервісів **`auth-run-hl`** / **`file-link-hl`** — **`namespace: dev`** у base та patch **`…/backendRefs/…/namespace`** у **ua**)), гілки **dev**, **ua** у **clean-merged-branch**, а також заборона тримати артефакти **Firebase Hosting** у **підкаталогах першого рівня** (безпосередні діти кореня репозиторію; у самому корені ці імена не вимагаються до видалення).
8
8
 
9
+ ## Активація
10
+
11
+ Правило активується через **`.n-cursor.json`** у корені репозиторію:
12
+
13
+ ```json
14
+ { "rules": ["abie"] }
15
+ ```
16
+
17
+ Без цього запису `@nitra/cursor` пропускає всі abie-перевірки (JS-концерни та rego-полісі).
18
+
9
19
  [k8s-hc-yaml](./js/hc_pairing.mdc)
10
20
 
21
+ [k8s-http-route-base](./js/http_route_base.mdc)
22
+
11
23
  [k8s-http-route-ua](./js/ua_http_route.mdc)
12
24
 
13
25
  [k8s-nodeselector](./js/ua_node_selector.mdc)
@@ -1,7 +1,7 @@
1
1
  /**
2
- * Автовизначення правил для `.n-cursor.json` за meta-даними з `npm/rules/<id>/meta.json`.
2
+ * Автовизначення правил для `.n-cursor.json` за meta-даними з `npm/rules/<id>/main.json`.
3
3
  *
4
- * Основна роль: `discoverRuleAutoActivation` читає `npm/rules/<id>/meta.json`, виводить
4
+ * Основна роль: `discoverRuleAutoActivation` читає `npm/rules/<id>/main.json`, виводить
5
5
  * `AUTO_RULE_ORDER` (алфавітно) і `AUTO_RULE_DEPENDENCIES` з meta, а потім для кожного правила
6
6
  * обчислює spec активації через `specMatches`: `always` — безумовно; `glob` — перевірка
7
7
  * файлів через `globToRegex`; `predicate` — незводимий предикат із реєстру `RULE_PREDICATES`
@@ -11,7 +11,7 @@
11
11
  *
12
12
  * Враховує винятки `disable-rules`: елементи зі списку не додаються автоматично.
13
13
  *
14
- * Автодетект скілів — у `./auto-skills.mjs` (умови — у `npm/skills/<skill>/meta.json`).
14
+ * Автодетект скілів — у `./auto-skills.mjs` (умови — у `npm/skills/<skill>/main.json`).
15
15
  * `mergeConfigWithAutoDetected` нижче приймає вже виявлені rules і skills і вливає
16
16
  * їх у конфіг із поправкою на legacy-id (`migrateRuleIds`).
17
17
  */
@@ -45,7 +45,7 @@ const PACKAGE_ROOT = dirname(dirname(fileURLToPath(import.meta.url)))
45
45
  const RULES_DIR = join(PACKAGE_ROOT, 'rules')
46
46
 
47
47
  /**
48
- * Скан `npm/rules/<id>/meta.json` → мапа id → RuleAutoSpec (лише правила з розпізнаним auto).
48
+ * Скан `npm/rules/<id>/main.json` → мапа id → RuleAutoSpec (лише правила з розпізнаним auto).
49
49
  * @param {string} [rulesDir] override для тестів
50
50
  * @returns {Record<string, import('./lib/rule-meta.mjs').RuleAutoSpec>} мапа автоактивації
51
51
  */
@@ -205,7 +205,7 @@ async function processFileEntry(absPath, root, facts) {
205
205
  * Обходить дерево проєкту, збираючи content-факти для предикатів автоувімкнення.
206
206
  *
207
207
  * `hasRegoFile` і `hasTempoDir` лишаються для зворотної сумісності з прямими читачами
208
- * фактів (тести, зовнішній код); саме автоувімкнення тепер data-driven через meta.json.
208
+ * фактів (тести, зовнішній код); саме автоувімкнення тепер data-driven через main.json.
209
209
  * @param {string} root абсолютний шлях кореня репозиторію
210
210
  * @returns {Promise<{
211
211
  * hasBunSqlImport: boolean,
@@ -350,7 +350,7 @@ function specMatches(spec, ctx) {
350
350
  }
351
351
 
352
352
  /**
353
- * Визначає авто-правила згідно з `rules/<rule>/meta.json`.
353
+ * Визначає авто-правила згідно з `rules/<rule>/main.json`.
354
354
  * @param {object} params параметри аналізу
355
355
  * @param {string} params.root абсолютний шлях до кореня репозиторію
356
356
  * @param {string[]} params.availableRules перелік доступних правил з пакету
@@ -1,7 +1,7 @@
1
1
  /**
2
- * Автовизначення skills для `.n-cursor.json` за умовами з `npm/skills/<skill>/meta.json`.
2
+ * Автовизначення skills для `.n-cursor.json` за умовами з `npm/skills/<skill>/main.json`.
3
3
  *
4
- * `meta.json` — джерело правди (а не hardcoded мапа). Підтримуються три варіанти:
4
+ * `main.json` — джерело правди (а не hardcoded мапа). Підтримуються три варіанти:
5
5
  *
6
6
  * - `auto: "завжди"` — скіл активується незалежно від інших правил
7
7
  * (приклади: `fix`, `lint`, `llm-patch`, `publish-telegram`).
@@ -26,7 +26,7 @@ const SKILLS_DIR = join(PACKAGE_ROOT, 'skills')
26
26
  */
27
27
 
28
28
  /**
29
- * Сканує `npm/skills/<id>/meta.json`. Скіли без `meta.json` або без розпізнаного
29
+ * Сканує `npm/skills/<id>/main.json`. Скіли без `main.json` або без розпізнаного
30
30
  * `auto` не потрапляють у результат — їх вмикають лише вручну в конфізі.
31
31
  * @param {string} [skillsDir] override для тестів
32
32
  * @returns {Record<string, SkillAutoSpec>} мапа `skillId → spec`
@@ -3,48 +3,34 @@ type: JS Module
3
3
  title: auto-rules.mjs
4
4
  resource: npm/scripts/auto-rules.mjs
5
5
  docgen:
6
- crc: d50b922f
6
+ crc: ba75c709
7
+ model: omlx/gemma-4-e4b-it-OptiQ-4bit
7
8
  score: 90
8
9
  ---
9
10
 
10
- Файл читає метадані з `npm/rules/<id>/meta.json` для автоматичного визначення порядку та залежностей правил. Він обчислює spec активації для кожного правила, використовуючи дані з `RULE_PREDICATES` з `lib/rule-predicates.mjs`, визначає активні правила, обчислює залежності та об'єднує конфігурацію з виявленими правилами та поправками на legacy-id. Код спирається на конфіги `.n-cursor.json`, `meta.json` та `package.json`.
11
+ ## Огляд
11
12
 
12
- ## Поведінка
13
-
14
- discoverRuleAutoActivation
15
- Читає meta-дані з файлів npm/rules/<id>/meta.json для визначення автоактивації правил.
16
-
17
- AUTO_RULE_ORDER
18
- Повертає алфавітний порядок для правил.
13
+ Автоматично визначає правила та скіли для конфігурації `.n-cursor.json`, скануючи мета-дані з `npm/rules/<id>/main.json` та аналізуючи структуру проєкту, зокрема `package.json`. Система виводить `AUTO_RULE_ORDER` (алфавітно) та `AUTO_RULE_DEPENDENCIES` для кожного правила. Для кожного правила обчислюється специфікація активації (`specMatches`), яка може бути безумовною (`always`), заснованою на шаблонах файлів (`glob`), або предикатною. Процес враховує винятки (`disable-rules`) та виконує транзитивне розгортання залежностей. Збираються контент-факти (GQL, bun-sql, hasura) для точного застосування правил. Також відбувається автоматичне виявлення скілів з `./auto-skills.mjs`, після чого всі виявлені правила та скіли зливаються у конфіг, враховуючи міграцію ID.
19
14
 
20
- AUTO_RULE_DEPENDENCIES
21
- Повертає граф залежностей між правилами.
22
-
23
- collectAutoRuleFacts
24
- Збирає контент-факти для предикатів, включаючи сканування GQL, Bun SQL та налаштувань Hasura.
25
-
26
- detectAutoRules
27
- Визначає активні правила на основі spec, перевіряючи їх проти згенерованих фактів.
15
+ ## Поведінка
28
16
 
29
- mergeConfigWithAutoDetected
30
- Доповнює конфігурацію, додаючи визначені автоправила та налаштування, з урахуванням legacy-ID; за наявності `availableRules`/`availableSkills` ще й відсіює з `rules`/`skills` неактуальні id, яких немає у пакеті (повертає їх у полі `pruned`).
17
+ discoverRuleAutoActivation сканує директорію `rules` та виявляє мета-дані для автоматичного визначення правил.
18
+ AUTO_RULE_ORDER надає стабільний алфавітний порядок для всіх правил, виявлених під час автоматичного визначення.
19
+ AUTO_RULE_DEPENDENCIES визначає транзитивні залежності між правилами, виявленими під час автоматичного визначення.
20
+ collectAutoRuleFacts обходить дерево проєкту, збираючи контент-факти про наявність певних структур (наприклад, GQL, Hasura, Rego).
21
+ detectAutoRules визначає список правил, які мають бути активні, на основі мета-даних правил та зібраних контент-фактів, враховуючи виключення.
22
+ mergeConfigWithAutoDetected об'єднує конфігурацію користувача з результатами автоматичного визначення правил та скілів, прибираючи з конфігу ті елементи, яких більше немає у пакеті.
31
23
 
32
24
  ## Публічний API
33
25
 
34
- discoverRuleAutoActivation — Скан `npm/rules/<id>/meta.json` мапа id RuleAutoSpec (лише правила з розпізнаним auto).
35
- AUTO_RULE_ORDER — Стабільний алфавітний порядок (замість хардкод-масиву).
36
- AUTO_RULE_DEPENDENCIES — Граф залежностей із meta (Type C) — замість хардкод-константи.
37
- collectAutoRuleFacts — Обходить дерево проєкту, збираючи content-факти для предикатів автоувімкнення.
38
- hasRegoFileФлаг наявності файлу Rego.
39
- hasTempoDirФлаг наявності директорії Tempo.
40
- hasBunSqlImport — Булеве значення про імпорт BunSQL.
41
- hasGqlTaggedTemplates — Булеве значення про наявність GQL-тегів.
42
- hasHasuraConfig — Булеве значення про конфігурацію Hasura.
26
+ discoverRuleAutoActivation — Зчитує `main.json` для кожного правила у `npm/rules/<id>/` та створює список правил, які можуть активуватися автоматично.
27
+ AUTO_RULE_ORDER — Визначає порядок застосування автоматичних правил за алфавітом.
28
+ AUTO_RULE_DEPENDENCIES — Створює граф залежностей між автоматичними правилами, використовуючи метадані.
29
+ collectAutoRuleFacts — Сканує структуру проєкту та збирає факти про вміст, необхідні для визначення, які автоматичні правила активувати.
30
+ detectAutoRulesВизначає, які автоматичні правила доступні на основі файлу `main.json` кожного правила.
31
+ mergeConfigWithAutoDetectedОбновлює конфігурацію, додаючи автоматично виявлені правила, і очищає список доступних правил/навичок від тих, що більше не існують у пакеті, фіксуючи видалені ID у полі `pruned`.
43
32
 
44
33
  ## Гарантії поведінки
45
34
 
46
- - Read-only: файл не виконує операцій запису у файлову систему.
47
35
  - Перехоплює помилки і не пропускає винятків назовні (fail-safe).
48
- - За невдачі повертає значення помилки (`false`/`null`/`Err`) замість генерування винятку чи паніки.
49
36
  - Свідомо пропускає шляхи: `.git`, `node_modules`.
50
- - Не звертається до мережі.
@@ -3,175 +3,30 @@ type: JS Module
3
3
  title: auto-skills.mjs
4
4
  resource: npm/scripts/auto-skills.mjs
5
5
  docgen:
6
- crc: 44328898
6
+ crc: 374d78b5
7
+ model: omlx/gemma-4-e4b-it-OptiQ-4bit
8
+ score: 100
7
9
  ---
8
10
 
9
- Модуль `npm/scripts/auto-skills.mjs` відповідає за **автовизначення (auto-activation) скілів** для файлу конфігурації `.n-cursor.json`. Він сканує директорію `npm/skills/` і для кожного скілу читає його `meta.json`, щоб визначити, чи має скіл активуватися автоматично — завжди або лише за наявності певних виявлених auto-правил (rules).
11
+ ## Огляд
10
12
 
11
- Ключова ідея модуля: **`meta.json` єдине джерело правди**. У коді немає жорстко прописаної мапи відповідностей між скілами та правилами; усе зчитується з метаданих скіла. Раніше використовувався hardcoded `AUTO_SKILL_ORDER`, тепер він обчислюється динамічно експорт залишено для зворотної сумісності.
13
+ Визначає, які скіли мають автоматично активуватися, скануючи `npm/skills/` та аналізуючи `main.json` кожного скілу. Логіка активації базується на конфігурації скілу: скіл може активуватися завжди (`auto: "завжди"`), якщо всі перелічені правила виявлені (`auto: ["rule", …]`), або бути opt-in, якщо поле `auto` відсутнє у `main.json`. Це забезпечує, що визначення автоматичної активації скілів є детермінованим, оскільки `main.json` є джерелом правди. Результати сканування використовуються для встановлення `AUTO_SKILL_ORDER` та `AUTO_SKILL_RULE_DEPENDENCIES`, що впливає на роботу з `.n-cursor.json`.
12
14
 
13
- Підтримуються три формати поля `auto` у `meta.json`:
15
+ ## Поведінка
14
16
 
15
- - `auto: "завжди"` скіл активується незавжди, незалежно від інших правил. Приклади за коментарями у файлі: `fix`, `lint`, `llm-patch`, `publish-telegram`.
16
- - `auto: ["rule", …]` скіл активується, якщо **усі** перелічені правила вже виявлено auto-rules-модулем. Приклади за коментарями: `adr-normalize` залежить від `["adr"]`, `taze` — від `["bun"]`.
17
- - поле `auto` відсутнє або формат не розпізнано скіл лише opt-in (тільки через `.n-cursor.json:skills`).
17
+ discoverSkillAutoActivation сканує директорію `npm/skills/` і визначає специфікації автоматичної активації скілів на основі вмісту `main.json` кожного скілу.
18
+ AUTO_SKILL_ORDER надає стабільний алфавітний порядок усіх скілів, які мають визначену автоматичну активацію.
19
+ AUTO_SKILL_RULE_DEPENDENCIES надає мапу скілів, які залежать від певних правил, для забезпечення зворотної сумісності.
20
+ detectAutoSkills визначає, які скіли мають бути автоматично активовані, порівнюючи доступні скіли з виявленими правилами та специфікаціями активації.
18
21
 
19
- Сканування `npm/skills/` виконується **синхронно під час завантаження модуля**: це дає детермінізм результату і узгоджується з sync-API сусіднього модуля `auto-rules.mjs`. Результат кешується на час життя процесу (`SKILL_AUTO_ACTIVATION`).
22
+ ## Публічний API
20
23
 
21
- ## Експорти / API
24
+ discoverSkillAutoActivation Знаходить скіли, які мають файл `main.json` у відповідній директорії, і які мають автоматичну активацію.
25
+ AUTO_SKILL_ORDER — Забезпечує фіксований алфавітний порядок скілів, що автоматично активуються, для підтримки старої версії.
26
+ AUTO_SKILL_RULE_DEPENDENCIES — Створює список скілів, що автоматично активуються і мають визначені правила залежностей.
27
+ detectAutoSkills — Виявляє скіли, які мають автоматичну активацію на основі вмісту файлу `auto.md` у директорії скілу.
22
28
 
23
- Модуль експортує:
29
+ ## Гарантії поведінки
24
30
 
25
- | Символ | Тип | Призначення |
26
- | ---------------------------------------------------------------------- | --------------------------------------------- | ------------------------------------------------------------------------ |
27
- | `discoverSkillAutoActivation(skillsDir?)` | function | Сканує директорію зі скілами та повертає мапу `skillId → SkillAutoSpec`. |
28
- | `AUTO_SKILL_ORDER` | `readonly string[]` (frozen) | Стабільний алфавітний список id скілів, які мають авто-активацію. |
29
- | `AUTO_SKILL_RULE_DEPENDENCIES` | `Readonly<Record<string, readonly string[]>>` | Лише ті скіли, у яких `auto: [rule, …]` — мапа `skillId → rules[]`. |
30
- | `detectAutoSkills({ availableSkills, detectedRules, disableSkills? })` | function | Обчислює фінальний список авто-скілів за станом середовища. |
31
-
32
- Тип `SkillAutoSpec` (визначається JSDoc-typedef):
33
-
34
- ```js
35
- /** @typedef {{ always: true } | { rules: readonly string[] }} SkillAutoSpec */
36
- ```
37
-
38
- Тобто кожен скіл, що пройшов парсинг, або має `always: true`, або несе масив `rules`.
39
-
40
- ## Функції
41
-
42
- ### `discoverSkillAutoActivation(skillsDir = SKILLS_DIR)`
43
-
44
- **Сигнатура:**
45
-
46
- ```js
47
- function discoverSkillAutoActivation(skillsDir?: string): Record<string, SkillAutoSpec>
48
- ```
49
-
50
- **Параметри:**
51
-
52
- - `skillsDir` _(string, optional)_ — шлях до директорії зі скілами. За замовчуванням — `SKILLS_DIR = join(PACKAGE_ROOT, 'skills')`, де `PACKAGE_ROOT = dirname(dirname(fileURLToPath(import.meta.url)))` (тобто корінь npm-пакету). Параметр існує для override у тестах.
53
-
54
- **Повертає:** `Record<string, SkillAutoSpec>` — мапа `skillId (== ім'я піддиректорії) → spec`.
55
-
56
- **Поведінка:**
57
-
58
- 1. Якщо `skillsDir` не існує — повертається порожній обʼєкт `{}`.
59
- 2. Інакше викликається `readdirSync(skillsDir, { withFileTypes: true })`.
60
- 3. Для кожного запису:
61
- - пропускаються файли (не директорії) та все, що починається з `.` (наприклад, приховані).
62
- - читається `meta.json` через `readSkillMetaRaw(...)`; якщо raw-обʼєкт відсутній (`null`/`undefined`) — скіл пропускається.
63
- - поле `raw.auto` пропускається через `parseSkillAutoSpec(...)`; якщо розпізнано — записується в `out[entry.name]`.
64
- 4. Скіли без розпізнаного `auto` **не потрапляють у результат** — вони можуть бути ввімкнені лише вручну через `.n-cursor.json:skills`.
65
-
66
- **Side effects:** sync I/O — `existsSync`, `readdirSync`, читання `meta.json` усередині `readSkillMetaRaw`. Інших побічних ефектів немає.
67
-
68
- ### `detectAutoSkills({ availableSkills, detectedRules, disableSkills })`
69
-
70
- **Сигнатура:**
71
-
72
- ```js
73
- function detectAutoSkills(params: {
74
- availableSkills: string[],
75
- detectedRules: string[],
76
- disableSkills?: string[],
77
- }): { skills: string[] }
78
- ```
79
-
80
- **Параметри:**
81
-
82
- - `availableSkills` _(string[])_ — перелік id скілів, доступних у поточній збірці пакету (без префіксу `n-`). Будь-який скіл, який є в `SKILL_AUTO_ACTIVATION`, але відсутній у `availableSkills`, **не активується**.
83
- - `detectedRules` _(string[])_ — id правил, що їх виявив auto-rules-крок; використовується як множина "виявлених" залежностей для специфікацій `{ rules: [...] }`.
84
- - `disableSkills` _(string[], optional)_ — список id скілів із `.n-cursor.json` із прапором `disable-skills`. За замовчуванням — заморожений пустий масив `DEFAULT_DISABLED_LIST`.
85
-
86
- **Повертає:** `{ skills: string[] }` — список id активованих скілів у **стабільному алфавітному порядку** (через `AUTO_SKILL_ORDER.filter(...)`).
87
-
88
- **Алгоритм:**
89
-
90
- 1. Нормалізує `availableSkills` у `Set` (lowercase, trim).
91
- 2. Будує `Set` із `disableSkills` та `detectedRules`.
92
- 3. Для кожної пари `[skillId, spec]` у `SKILL_AUTO_ACTIVATION`:
93
- - якщо скіл не входить у `normalizedSkills` або входить у `disableSkillsSet` — пропуск.
94
- - якщо `spec` має `always: true` **або** усі `spec.rules` присутні в `detectedRulesSet` — скіл додається до результуючого `detected`.
95
- 4. Фінальний список будується через `AUTO_SKILL_ORDER.filter(id => detected.has(id))`, що гарантує детермінований алфавітний порядок та фільтрацію тільки тих id, які реально мають spec.
96
-
97
- **Side effects:** немає — функція чиста. Використовує тільки заздалегідь обчислений `SKILL_AUTO_ACTIVATION` і `AUTO_SKILL_ORDER`.
98
-
99
- ## Внутрішні константи модуля
100
-
101
- - `PACKAGE_ROOT` — корінь npm-пакету: `dirname(dirname(fileURLToPath(import.meta.url)))`. Тобто два рівні вгору від `npm/scripts/auto-skills.mjs` → `npm/`.
102
- - `SKILLS_DIR` — `join(PACKAGE_ROOT, 'skills')`, тобто `npm/skills/`.
103
- - `SKILL_AUTO_ACTIVATION` — результат `discoverSkillAutoActivation()` під час імпорту модуля; кеш на час процесу.
104
- - `AUTO_SKILL_ORDER` — `Object.freeze(Object.keys(SKILL_AUTO_ACTIVATION).toSorted(localeCompare))`. Заморожений алфавітний список усіх скілів з auto-spec.
105
- - `AUTO_SKILL_RULE_DEPENDENCIES` — `Object.freeze(Object.fromEntries(...))`: похідна view, де лишаються тільки записи зі spec-формою `{ rules }`. Призначена для зворотної сумісності й для автодоку.
106
- - `DEFAULT_DISABLED_LIST` — `Object.freeze([])`, дефолтне значення для параметра `disableSkills`.
107
-
108
- ## Залежності
109
-
110
- **Node.js стандартні модулі:**
111
-
112
- - `node:fs` — `existsSync`, `readdirSync` (синхронне сканування директорії).
113
- - `node:path` — `dirname`, `join`.
114
- - `node:url` — `fileURLToPath` (для отримання абсолютного шляху модуля з `import.meta.url`).
115
-
116
- **Локальні модулі:**
117
-
118
- - `./lib/skill-meta.mjs` — імпортуються:
119
- - `readSkillMetaRaw(skillPath)` — читає сирий обʼєкт `meta.json` за шляхом до директорії скілу.
120
- - `parseSkillAutoSpec(raw.auto)` — нормалізує значення `auto` у `SkillAutoSpec` (`{ always: true }`, `{ rules: [...] }` або `null`).
121
-
122
- **Файлова система (рантайм-залежності):**
123
-
124
- - Очікується наявність директорії `npm/skills/` із піддиректоріями `<skillId>/meta.json`. Відсутність директорії оброблена коректно (повертається `{}`).
125
-
126
- ## Потік виконання / Використання
127
-
128
- ### Завантаження модуля (init phase)
129
-
130
- 1. `PACKAGE_ROOT` і `SKILLS_DIR` обчислюються на основі `import.meta.url`.
131
- 2. Викликається `discoverSkillAutoActivation()` — це **синхронне** I/O під час імпорту: читається `npm/skills/`, з кожної піддиректорії — `meta.json`. Результат зберігається у `SKILL_AUTO_ACTIVATION`.
132
- 3. `AUTO_SKILL_ORDER` і `AUTO_SKILL_RULE_DEPENDENCIES` похідні від цього кешу — обчислюються одноразово і заморожуються.
133
-
134
- ### Виклик `detectAutoSkills` (runtime)
135
-
136
- Зазвичай викликається на етапі генерації / валідації `.n-cursor.json`. Послідовність:
137
-
138
- 1. Зовнішній код визначає `availableSkills` (зі стану пакету / маніфесту) та `detectedRules` (через сусідній auto-rules pipeline).
139
- 2. Опціонально передає `disableSkills` із конфігу користувача.
140
- 3. Функція повертає `{ skills: [...] }` — фінальний відсортований список id, готовий до запису у конфіг.
141
-
142
- ### Приклад використання
143
-
144
- ```js
145
- import { detectAutoSkills, AUTO_SKILL_ORDER, AUTO_SKILL_RULE_DEPENDENCIES } from './auto-skills.mjs'
146
-
147
- const { skills } = detectAutoSkills({
148
- availableSkills: ['fix', 'lint', 'adr-normalize', 'taze', 'publish-telegram'],
149
- detectedRules: ['adr', 'bun'],
150
- disableSkills: ['publish-telegram']
151
- })
152
-
153
- // skills буде у стабільному алфавітному порядку:
154
- // напр. ['adr-normalize', 'fix', 'lint', 'taze']
155
- // (publish-telegram вимкнено через disableSkills)
156
- ```
157
-
158
- ### Контракти й інваріанти
159
-
160
- - **Детермінізм:** порядок результату повністю визначається `AUTO_SKILL_ORDER`, який є `localeCompare`-сортованим snapshot-ом на момент імпорту.
161
- - **Безпека до відсутніх скілів:** скіли, доступні у `SKILL_AUTO_ACTIVATION`, але не присутні у `availableSkills`, ніколи не активуються.
162
- - **Кеш:** перечитати `npm/skills/` без перезавантаження модуля неможливо — функція `discoverSkillAutoActivation` тут лише для прямого виклику з тестів (передаючи інший `skillsDir`).
163
- - **Опт-аут:** `disableSkills` має пріоритет над `auto`-активацією.
164
-
165
- ## Rebuild Test
166
-
167
- Уявімо, що файл загублено. За цим описом його можна відновити так:
168
-
169
- 1. ESM-модуль із Node-імпортами `existsSync, readdirSync` із `node:fs`, `dirname, join` із `node:path`, `fileURLToPath` із `node:url`.
170
- 2. Імпорт `parseSkillAutoSpec, readSkillMetaRaw` із `./lib/skill-meta.mjs`.
171
- 3. Константи `PACKAGE_ROOT = dirname(dirname(fileURLToPath(import.meta.url)))`, `SKILLS_DIR = join(PACKAGE_ROOT, 'skills')`.
172
- 4. Експортована функція `discoverSkillAutoActivation(skillsDir = SKILLS_DIR)`: якщо `!existsSync(skillsDir)` → `{}`; інакше readdirSync з `withFileTypes`, ітерувати, пропускати не-директорії та `name.startsWith('.')`, читати `readSkillMetaRaw(join(skillsDir, entry.name))`, пропускати falsy, парсити `parseSkillAutoSpec(raw.auto)`, додавати в `out[entry.name]` тільки якщо парсер повернув spec.
173
- 5. Константа модуля `SKILL_AUTO_ACTIVATION = discoverSkillAutoActivation()`.
174
- 6. Експорт `AUTO_SKILL_ORDER = Object.freeze(Object.keys(SKILL_AUTO_ACTIVATION).toSorted((a,b) => a.localeCompare(b)))`.
175
- 7. Експорт `AUTO_SKILL_RULE_DEPENDENCIES = Object.freeze(Object.fromEntries(Object.entries(SKILL_AUTO_ACTIVATION).filter(([, spec]) => 'rules' in spec).map(([id, spec]) => [id, spec.rules])))`.
176
- 8. Константа `DEFAULT_DISABLED_LIST = Object.freeze([])`.
177
- 9. Експортована функція `detectAutoSkills({ availableSkills, detectedRules, disableSkills = DEFAULT_DISABLED_LIST })`: побудувати `normalizedSkills = new Set(availableSkills.map(s => s.trim().toLowerCase()))`, `disableSkillsSet`, `detectedRulesSet`; пройти `Object.entries(SKILL_AUTO_ACTIVATION)`, пропустити коли скіл не у `normalizedSkills` або у `disableSkillsSet`, інакше додати до `detected` якщо `'always' in spec` або `spec.rules.every(d => detectedRulesSet.has(d))`; повернути `{ skills: AUTO_SKILL_ORDER.filter(id => detected.has(id)) }`.
31
+ - Read-only: не виконує операцій запису (ФС/БД).
32
+ - Кешує результати в межах одного прогону.
@@ -3,31 +3,31 @@ type: JS Module
3
3
  title: mirror-parity.mjs
4
4
  resource: npm/scripts/lib/mirror-parity.mjs
5
5
  docgen:
6
- crc: 5e366df1
6
+ crc: 093ff2bb
7
7
  model: omlx/gemma-4-e4b-it-OptiQ-4bit
8
8
  score: 90
9
9
  ---
10
10
 
11
11
  ## Огляд
12
12
 
13
- Модуль порівнює вміст дзеркал правил (`.cursor/rules/n-<id>.mdc`) з канонічними версіями (`npm/rules/<id>/<id>.mdc`), які містять застосовані трансформації (трансформ, що застосовує `readBundledRuleContent` $\to$ `inlineTemplateLinks`). Він визначає список керованих дзеркал, формує очікуваний вміст для кожного дзеркала та виявляє дрейф — відхилення фактичного вмісту від очікуваного.
13
+ Модуль забезпечує паритет дзеркал правил, порівнюючи вміст `.cursor/rules/n-<id>.mdc` з канонічним вмістом `npm/rules/<id>/<id>.mdc`. Він визначає, які дзеркала відстежувати, формує очікуваний вміст цих дзеркал після застосування шаблонів (трансформу, що застосовує `readBundledRuleContent` $\rightarrow$ `inlineTemplateLinks`), та виявляє дрейф, що виникає, коли канонічний `.mdc` змінюється без регенерації дзеркала.
14
14
 
15
15
  ## Поведінка
16
16
 
17
17
  listManagedMirrors
18
- Визначає список керованих дзеркал правил, які мають відповідне канонічне джерело у `npm/rules`.
18
+ Визначає список керованих дзеркал правил, що мають канонічне джерело у `npm/rules`.
19
19
 
20
20
  expectedMirrorContent
21
21
  Формує очікуваний вміст дзеркала, застосовуючи трансформації до канонічного файлу.
22
22
 
23
23
  findMirrorDrift
24
- Виявляє ідентифікатори дзеркал, чий фактичний вміст відрізняється від очікуваного вмісту, отриманого з канону.
24
+ Виявляє ідентифікатори дзеркал, чий фактичний вміст відрізняється від очікуваного.
25
25
 
26
26
  ## Публічний API
27
27
 
28
- listManagedMirrors — перераховує керовані дзеркала, які мають визначене канонічне джерело.
29
- expectedMirrorContent — визначає бажаний вміст дзеркала, використовуючи канон із вбудованими шаблонами.
30
- findMirrorDrift — знаходить ідентифікатори дзеркал, у яких фактичний вміст відрізняється від очікуваного.
28
+ listManagedMirrors — перераховує керовані дзеркала, які мають визначене основне джерело.
29
+ expectedMirrorContent — визначає бажаний вміст дзеркала, використовуючи шаблонне заміщення даних.
30
+ findMirrorDrift — знаходить ідентифікатори дзеркал, чий фактичний вміст відрізняється від очікуваного.
31
31
 
32
32
  ## Гарантії поведінки
33
33
 
@@ -3,30 +3,30 @@ type: JS Module
3
3
  title: rule-meta.mjs
4
4
  resource: npm/scripts/lib/rule-meta.mjs
5
5
  docgen:
6
- crc: 36aea8cb
6
+ crc: 8eca71d2
7
7
  model: omlx/gemma-4-e4b-it-OptiQ-4bit
8
8
  score: 100
9
9
  ---
10
10
 
11
11
  ## Огляд
12
12
 
13
- Парсер інтерпретує метадані правил, що знаходяться у `npm/rules/<id>/meta.json`. Він реалізує data-driven логіку для визначення умов активації кожного детектора. Специфікації активації (`auto`) нормалізуються на основі вмісту `meta.json`, підтримуючи чотири типи: константа `RULE_ALWAYS` ("завжди"), залежності від інших правил, шаблони за допомогою `glob`, або незводимі предикати. Парсер не виконує операцій запису у файлову систему чи бази даних і забезпечує безпечну роботу, перехоплюючи помилки.
13
+ Файл зчитує метадані правил з `npm/rules/<id>/main.json`. Він нормалізує специфікації активації (`auto`) та області застосування (`lint`). Специфікація `main.json.auto` може мати чотири форми: константу `RULE_ALWAYS` ("завжди"), масив залежних правил, об'єкт з шаблоном `glob` або об'єкт з предикатом. Це забезпечує механізм для визначення умов активації правила на основі конфігурації `main.json`.
14
14
 
15
15
  ## Поведінка
16
16
 
17
- RULE_ALWAYS — константа, що позначає безумовну активацію правила.
18
- parseRuleAutoSpec — Нормалізує значення поля `auto` з метаданих правила у дискриміновану специфікацію активації.
19
- parseRuleLintSpec — Нормалізує значення поля `lint` з метаданих правила у специфікацію області застосування детектора.
20
- readRuleMetaRaw — Читає та парсить вміст `main.json` з каталогу правила, повертаючи його як об'єкт або `null` у разі помилки чи відсутності файлу.
17
+ RULE_ALWAYS — Константа, що позначає безумовну активацію правила.
18
+ parseRuleAutoSpec — Нормалізує значення поля `auto` з `main.json` у дискриміновану специфікацію активації правила.
19
+ parseRuleLintSpec — Нормалізує значення поля `lint` з `main.json` у специфікацію області застосування детектора.
20
+ readRuleMetaRaw — Зчитує та парсить вміст `main.json` з каталогу правила, повертаючи його як об'єкт або `null` у разі помилки чи відсутності файлу.
21
21
 
22
22
  ## Публічний API
23
23
 
24
- RULE_ALWAYS — константа, що вказує на безумовну активацію.
25
- parseRuleAutoSpec — перетворює налаштування автоматичного визначення правил з `meta.json` у структурований формат.
26
- parseRuleLintSpec — перетворює налаштування лінтування з `meta.json` у визначення області дії детектора.
27
- "per-file" — визначає, що детектор працює з окремими зміненими файлами (порівняння змін з оригіналом).
28
- "full" — вказує на повний, нероздільний аналіз між усіма файлами (активується лише при використанні прапорця `--full` або в CI).
29
- readRuleMetaRaw — зчитує та обробляє метадані одного правила з файлу `meta.json`.
24
+ RULE_ALWAYS — позначка для безумовної активації.
25
+ parseRuleAutoSpec — перетворює налаштування автоматичного визначення правил з `main.json` у структурований формат.
26
+ parseRuleLintSpec — перетворює налаштування лінтера з `main.json` у визначення області дії детектора.
27
+ "per-file" — визначає, що детектор аналізує зміни на рівні окремих файлів (порівнює відмінності з оригіналом).
28
+ "full" — визначає, що детектор аналізує весь проєкт одночасно (активується лише при використанні прапорця `--full` або в CI).
29
+ readRuleMetaRaw — зчитує та розбирає метадані одного правила з `main.json`.
30
30
 
31
31
  ## Гарантії поведінки
32
32
 
@@ -3,28 +3,28 @@ type: JS Module
3
3
  title: skill-meta.mjs
4
4
  resource: npm/scripts/lib/skill-meta.mjs
5
5
  docgen:
6
- crc: c0918db5
6
+ crc: c1757867
7
7
  model: omlx/gemma-4-e4b-it-OptiQ-4bit
8
8
  score: 100
9
9
  ---
10
10
 
11
11
  ## Огляд
12
12
 
13
- Спільний парсер метаданих скіла, що зчитує дані з `npm/skills/<id>/meta.json`. Він є єдиним джерелом правди для конфігурації скілів, визначаючи умови автоактивації (через поле `auto`, де `SKILL_ALWAYS` означає "завжди"), чи виконувати скіл в окремому git-worktree (`worktree`), та чи вимагає скіл запуску з кореня репозиторію (`requireRoot`). Модуль надає механізми для парсингу цих метаданих, перевірки вимог до кореня та читання сирих даних. Він працює в режимі fail-safe, перехоплюючи помилки та повертаючи порожнє значення замість винятків.
13
+ Спільний парсер метаданих скіла, що зчитує інформацію з `main.json`. Цей файл є єдиним джерелом правди для скіла. Модуль дозволяє визначати умови автоактивації скіла (через поле `auto`), вказувати, чи виконувати скіл в окремому git-worktree (`worktree`), та чи вимагає він запуску з кореня репозиторію (`requireRoot`). Надає константу `SKILL_ALWAYS` для безумовної активації. Хелпер використовується іншими компонентами для уникнення дублювання парсингу. Функції забезпечують перехоплення помилок (fail-safe), повертаючи порожнє значення замість винятків.
14
14
 
15
15
  ## Поведінка
16
16
 
17
17
  SKILL_ALWAYS — надає літерал для безумовної автоактивації скіла.
18
- parseSkillAutoSpec — перетворює значення поля `auto` з метаданих скіла у специфікацію автоактивації.
19
- skillRequiresRoot — визначає, чи вимагає скіл запуску з кореня репозиторію, виходячи з метаданих.
20
- readSkillMetaRaw — читає та парсить файл `main.json` у каталозі скіла, повертаючи його вміст або `null` у разі помилки.
18
+ parseSkillAutoSpec — перетворює значення поля `auto` з `main.json` у специфікацію автоактивації.
19
+ skillRequiresRoot — визначає, чи вимагає скіл запуску з кореня репозиторію, базуючись на метаданих.
20
+ readSkillMetaRaw — читає та парсить файл `main.json` для заданого каталогу скіла.
21
21
 
22
22
  ## Публічний API
23
23
 
24
- SKILL_ALWAYS — маркер, що вказує на безумовну активацію
25
- parseSkillAutoSpec — витягує налаштування автоматичного запуску з `meta.json`
26
- skillRequiresRoot — визначає, чи потрібен запуск скіла з кореня репозиторію
27
- readSkillMetaRaw — зчитує та обробляє метадані окремого скіла з `meta.json`
24
+ SKILL_ALWAYS — позначка для безумовної активації.
25
+ parseSkillAutoSpec — витягує налаштування автоматичного запуску з `main.json` у структуру `SkillAutoSpec`.
26
+ skillRequiresRoot — визначає, чи потрібен запуск скіла з кореня репозиторію (активує захист від запуску з інших місць).
27
+ readSkillMetaRaw — зчитує та розбирає метадані одного скіла з `main.json`.
28
28
 
29
29
  ## Гарантії поведінки
30
30
 
@@ -3,24 +3,26 @@ type: JS Module
3
3
  title: worktree-notice.mjs
4
4
  resource: npm/scripts/lib/worktree-notice.mjs
5
5
  docgen:
6
- crc: 1f7d5e0d
6
+ crc: b4358793
7
7
  model: omlx/gemma-4-e4b-it-OptiQ-4bit
8
8
  score: 100
9
9
  ---
10
10
 
11
- Цей файл вшиває worktree-інструкцію у синкнутий `SKILL.md` (рішення D2 зі spec). Коли `meta.json.worktree === true`, скіл вставляє/замінює ідемпотентний ре-синкнутий блок, що містить маркери WORKTREE_START та WORKTREE_END, забезпечуючи виконання скілу в окремому git-worktree та запобігаючи паралелізації. Функція `injectWorktreeNotice` керує наявністю або відсутністю цього блоку в `SKILL.md` на основі конфігурації.
11
+ ## Огляд
12
+
13
+ Управляє вставкою інструкцій для виконання команд у ізольованому git-worktree у синкнутий `SKILL.md` (рішення D2 зі spec). Коли `main.json.worktree === true`, інструкції вставляються між маркерами `WORKTREE_START` та `WORKTREE_END`. Це забезпечує ре-синк ідемпотентність: наявний блок замінюється, а при `main.json.worktree === false` — видаляється. Механізм адаптований для агента, який читає `SKILL.md`.
12
14
 
13
15
  ## Поведінка
14
16
 
15
- WORKTREE_START Маркер початку блоку інструкцій для роботи в окремому git-worktree.
16
- WORKTREE_END Маркер кінця блоку інструкцій для роботи в окремому git-worktree.
17
- injectWorktreeNotice Вставляє, оновлює або видаляє блок інструкцій для роботи в worktree у вмісті SKILL.md залежно від булевого значення.
17
+ WORKTREE_START: Позначає початок блоку інструкцій для роботи в окремому git-worktree.
18
+ WORKTREE_END: Позначає кінець блоку інструкцій для роботи в окремому git-worktree.
19
+ injectWorktreeNotice: Вставляє, оновлює або видаляє блок інструкцій для роботи в worktree у вмісті SKILL.md залежно від булевого значення.
18
20
 
19
21
  ## Публічний API
20
22
 
21
- WORKTREE_START — Позначає початок секції, що описує робоче дерево.
22
- WORKTREE_END — Позначає кінець секції, що описує робоче дерево.
23
- injectWorktreeNotice — Вставляє, змінює або видаляє блок інформації про робоче дерево у файлі `SKILL.md`.
23
+ WORKTREE_START — Позначає початок блоку, що описує робоче дерево.
24
+ WORKTREE_END — Позначає кінець блоку, що описує робоче дерево.
25
+ injectWorktreeNotice — Додає, змінює або видаляє блок робочого дерева у файлі `SKILL.md`.
24
26
 
25
27
  ## Гарантії поведінки
26
28
 
@@ -1,7 +1,7 @@
1
1
  /**
2
- * Парсер метаданих правила з `npm/rules/<id>/meta.json` (data-driven автодетект).
2
+ * Парсер метаданих правила з `npm/rules/<id>/main.json` (data-driven автодетект).
3
3
  *
4
- * `meta.json.auto` має один із чотирьох видів:
4
+ * `main.json.auto` має один із чотирьох видів:
5
5
  * - `"завжди"` → always-on;
6
6
  * - `["rule", …]` → активується, коли всі правила-залежності виявлені;
7
7
  * - `{ "glob": "<pat>" | [<pat>] }` → наявність файлів/каталогів за glob (OR);
@@ -20,7 +20,7 @@ export const RULE_ALWAYS = 'завжди'
20
20
  */
21
21
 
22
22
  /**
23
- * Нормалізує значення `meta.json.auto` у дискриміновану форму.
23
+ * Нормалізує значення `main.json.auto` у дискриміновану форму.
24
24
  * @param {unknown} value значення поля `auto`
25
25
  * @returns {RuleAutoSpec | null} `null` — формат не розпізнано (= opt-in)
26
26
  */
@@ -48,11 +48,11 @@ export function parseRuleAutoSpec(value) {
48
48
  return null
49
49
  }
50
50
 
51
- /** Допустимі значення `meta.json.lint` (вісь scope: чи детектор дробиться на changed-set). */
51
+ /** Допустимі значення `main.json.lint` (вісь scope: чи детектор дробиться на changed-set). */
52
52
  const LINT_SCOPES = new Set(['per-file', 'full'])
53
53
 
54
54
  /**
55
- * Нормалізує значення `meta.json.lint` у scope детектора.
55
+ * Нормалізує значення `main.json.lint` у scope детектора.
56
56
  * - `"per-file"` — детектор декомпозується на змінені файли (дельта vs origin);
57
57
  * - `"full"` — нероздільно крос-файловий (лише `--full` / CI).
58
58
  * Об'єктна форма `{scope, ci}` скасована: CI=`--read-only --full` ганяє все повністю,
@@ -65,7 +65,7 @@ export function parseRuleLintSpec(value) {
65
65
  }
66
66
 
67
67
  /**
68
- * Читає й парсить `meta.json` одного правила.
68
+ * Читає й парсить `main.json` одного правила.
69
69
  * @param {string} ruleDir абсолютний шлях до каталогу правила
70
70
  * @returns {Record<string, unknown> | null} обʼєкт або `null` (немає файлу / невалідний JSON / не-обʼєкт)
71
71
  */
@@ -1,7 +1,7 @@
1
1
  /**
2
- * Спільний парсер метаданих скіла з `npm/skills/<id>/meta.json`.
2
+ * Спільний парсер метаданих скіла з `npm/skills/<id>/main.json`.
3
3
  *
4
- * `meta.json` — єдине джерело правди для скіла замість колишнього `auto.md`:
4
+ * `main.json` — єдине джерело правди для скіла замість колишнього `auto.md`:
5
5
  * - `auto` — умова автоактивації (`"завжди"` | масив id правил), опційне;
6
6
  * - `worktree` — boolean: чи виконувати скіл в окремому git-worktree (один інстанс);
7
7
  * - `requireRoot` — boolean, опційне: чи скіл вимагає запуску з кореня репо.
@@ -24,8 +24,8 @@ export const SKILL_ALWAYS = 'завжди'
24
24
  */
25
25
 
26
26
  /**
27
- * Перетворює значення поля `auto` з `meta.json` у `SkillAutoSpec`.
28
- * @param {unknown} value значення `meta.json.auto`
27
+ * Перетворює значення поля `auto` з `main.json` у `SkillAutoSpec`.
28
+ * @param {unknown} value значення `main.json.auto`
29
29
  * @returns {SkillAutoSpec | null} `null` — формат не розпізнано (= opt-in)
30
30
  */
31
31
  export function parseSkillAutoSpec(value) {
@@ -43,7 +43,7 @@ export function parseSkillAutoSpec(value) {
43
43
  /**
44
44
  * Чи вимагає скіл запуску з кореня репо («активовано root-захист»). Єдина похідна
45
45
  * ознака: `worktree:true` (корінь гарантує worktree) АБО явний `requireRoot:true`.
46
- * @param {Record<string, unknown> | null} meta розпарсений `meta.json` (або null)
46
+ * @param {Record<string, unknown> | null} meta розпарсений `main.json` (або null)
47
47
  * @returns {boolean} true — скіл мутує проєкт і має стартувати з кореня
48
48
  */
49
49
  export function skillRequiresRoot(meta) {
@@ -51,7 +51,7 @@ export function skillRequiresRoot(meta) {
51
51
  }
52
52
 
53
53
  /**
54
- * Читає й парсить `meta.json` одного скіла.
54
+ * Читає й парсить `main.json` одного скіла.
55
55
  * @param {string} skillDir абсолютний шлях до каталогу скіла
56
56
  * @returns {Record<string, unknown> | null} розпарсений обʼєкт або `null` (немає файлу / невалідний JSON / не-обʼєкт)
57
57
  */
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Вшивання worktree-інструкції у синкнутий `SKILL.md` (рішення D2 зі spec).
3
3
  *
4
- * Коли `meta.json.worktree === true`, скіл має виконуватись в окремому git-worktree
4
+ * Коли `main.json.worktree === true`, скіл має виконуватись в окремому git-worktree
5
5
  * і не паралелитись. Підказка адресована агенту, який читає `SKILL.md`, тож
6
6
  * вставляється в текст між стабільними маркерами — ре-синк ідемпотентний:
7
7
  * наявний блок замінюється, при `worktree:false` — видаляється.
@@ -159,7 +159,7 @@ function buildBlock(content) {
159
159
  /**
160
160
  * Вставляє / оновлює / видаляє worktree-блок у вмісті `SKILL.md`.
161
161
  * @param {string} content вміст `SKILL.md`
162
- * @param {boolean} enabled чи має бути блок (значення `meta.json.worktree`)
162
+ * @param {boolean} enabled чи має бути блок (значення `main.json.worktree`)
163
163
  * @returns {string} оновлений вміст (ідемпотентно)
164
164
  */
165
165
  export function injectWorktreeNotice(content, enabled) {