@nitra/cursor 1.13.40 → 1.13.42

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
@@ -4,6 +4,19 @@
4
4
 
5
5
  Формат — [Keep a Changelog](https://keepachangelog.com/uk/1.1.0/), нумерація — [SemVer](https://semver.org/lang/uk/).
6
6
 
7
+ ## [1.13.42] - 2026-05-18
8
+
9
+ ### Added
10
+
11
+ - `efes` rule: новий (поки що порожній) пакет правил для проєктів **github.com/efes-cloud/***. Автодетект у `auto-rules.mjs` через `EFES_REPOSITORY_URL_MARKER` (`https://github.com/efes-cloud/`) — аналогічно до `abie`. Додано `npm/rules/efes/efes.mdc` + `auto.md`, прописано порядок в `AUTO_RULE_ORDER` і покрито тестами в `auto-rules.test.mjs`.
12
+ - `efes-create-env` skill: повʼязано з правилом `efes` через `skills/efes-create-env/auto.md` (`[efes]`) — активується автоматично, коли репозиторій відповідає efes-маркеру. Тести в `auto-skills.test.mjs` фіксують позитивний і негативний випадки.
13
+
14
+ ## [1.13.41] - 2026-05-18
15
+
16
+ ### Fixed
17
+
18
+ - `k8s` rule: yannh-патерн для груп з крапками — у назві файлу схеми зберігається лише **перший сегмент** `group` до першої крапки (`networking.k8s.io` → `networking`, `rbac.authorization.k8s.io` → `rbac`, `flowcontrol.apiserver.k8s.io` → `flowcontrol`); попередній `<group-з-крапками-як-дефіси>` давав 404 для всіх ресурсів `*.k8s.io` (Ingress, NetworkPolicy, ClusterRole, StorageClass, FlowSchema, RuntimeClass тощо). Виправлено в `expectedSchemaUrlForTypedManifest` і `buildNetworkPolicyYaml` (`check-k8s.mjs`); опис патерну в `k8s.mdc` переписано з прикладами для усіх типових груп. Bump `k8s.mdc` `1.34` → `1.35`.
19
+
7
20
  ## [1.13.40] - 2026-05-18
8
21
 
9
22
  ### Fixed
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nitra/cursor",
3
- "version": "1.13.40",
3
+ "version": "1.13.42",
4
4
  "description": "CLI для завантаження cursor-правил (префікс n-) у локальний репозиторій",
5
5
  "keywords": [
6
6
  "cli",
@@ -0,0 +1 @@
1
+ якщо в кореневому package.json в секції "repository" присутній текст "<https://github.com/efes-cloud/**/>"
@@ -0,0 +1,7 @@
1
+ ---
2
+ description: Правила для проєктів Efes (репозиторії під github.com/efes-cloud)
3
+ alwaysApply: true
4
+ version: '1.0'
5
+ ---
6
+
7
+ Правило **efes** для споживачів **@nitra/cursor** у репозиторіях під **`github.com/efes-cloud/*`**. Поки що зміст правила порожній — додавайте сюди вимоги, специфічні для efes-проєктів, у міру їх появи.
@@ -3595,10 +3595,14 @@ function expectedSchemaUrlForTypedManifest(doc, apiVersion, kind) {
3595
3595
  const group = apiVersion.slice(0, Math.max(0, slash))
3596
3596
  const version = apiVersion.slice(slash + 1)
3597
3597
  const kindPart = kindToSchemaFilePart(kind)
3598
- const groupDash = group.replaceAll('.', '-')
3599
3598
 
3600
3599
  if (YANNH_GROUPS.has(group)) {
3601
- const url = `${YANNH_BASE}${kindPart}-${groupDash}-${version}.json`
3600
+ // yannh для груп типу `*.k8s.io` / `*.apiserver.k8s.io` зберігає у назві файлу
3601
+ // лише перший сегмент `group` до першої крапки: `networking.k8s.io` → `networking`,
3602
+ // `rbac.authorization.k8s.io` → `rbac`, `flowcontrol.apiserver.k8s.io` → `flowcontrol`.
3603
+ // Для груп без крапок (`apps`, `batch`, `autoscaling`, `policy`) це збігається з group.
3604
+ const groupPart = group.split('.')[0]
3605
+ const url = `${YANNH_BASE}${kindPart}-${groupPart}-${version}.json`
3602
3606
  return { expected: url, reason: 'вбудований API Kubernetes (yannh)' }
3603
3607
  }
3604
3608
 
@@ -4284,7 +4288,7 @@ const NETWORK_POLICY_EGRESS_YAML = ` egress:
4284
4288
  * @returns {string} вміст `networkpolicy.yaml`
4285
4289
  */
4286
4290
  export function buildNetworkPolicyYaml(deployName, appLabel) {
4287
- const schemaUrl = `${YANNH_BASE}networkpolicy-networking-k8s-io-v1.json`
4291
+ const schemaUrl = `${YANNH_BASE}networkpolicy-networking-v1.json`
4288
4292
  return `# yaml-language-server: $schema=${schemaUrl}
4289
4293
  apiVersion: networking.k8s.io/v1
4290
4294
  kind: NetworkPolicy
package/rules/k8s/k8s.mdc CHANGED
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  description: K8s YAML — $schema (yaml-language-server); lint-k8s (kubeconform, kubescape); check-k8s
3
- version: '1.34'
3
+ version: '1.35'
4
4
  globs: "**/k8s/**/*.yaml"
5
5
  alwaysApply: false
6
6
  ---
@@ -471,7 +471,7 @@ resources:
471
471
  ```
472
472
 
473
473
  ```yaml title="k8s/components/networkpolicy.yaml"
474
- # yaml-language-server: $schema=https://raw.githubusercontent.com/yannh/kubernetes-json-schema/master/v1.33.9-standalone-strict/networkpolicy-networking-k8s-io-v1.json
474
+ # yaml-language-server: $schema=https://raw.githubusercontent.com/yannh/kubernetes-json-schema/master/v1.33.9-standalone-strict/networkpolicy-networking-v1.json
475
475
  apiVersion: networking.k8s.io/v1
476
476
  kind: NetworkPolicy
477
477
  metadata:
@@ -712,8 +712,8 @@ patch: |-
712
712
  ```
713
713
 
714
714
  3. **`apiVersion: group/version`** і **group** у **`YANNH_GROUPS`** у скрипті → yannh:
715
- `https://raw.githubusercontent.com/yannh/kubernetes-json-schema/master/<PIN>/<kind>-<group-з-крапками-як-дефіси>-<version>.json`
716
- Приклади: `apps/v1` + `Deployment` → `deployment-apps-v1.json`; `networking.k8s.io/v1` + `Ingress` → `ingress-networking-k8s-io-v1.json`.
715
+ `https://raw.githubusercontent.com/yannh/kubernetes-json-schema/master/<PIN>/<kind>-<group-частина>-<version>.json`
716
+ де **`<group-частина>`** — **перший сегмент** `group` до першої крапки: для груп без крапок збігається з усією group (`apps/v1` + `Deployment` → `deployment-apps-v1.json`); для `*.k8s.io` / `*.apiserver.k8s.io` — лише префікс до `.k8s.io` (`networking.k8s.io/v1` + `Ingress` → `ingress-networking-v1.json`; `networking.k8s.io/v1` + `NetworkPolicy` → `networkpolicy-networking-v1.json`; `rbac.authorization.k8s.io/v1` + `ClusterRole` → `clusterrole-rbac-v1.json`; `flowcontrol.apiserver.k8s.io/v1` + `FlowSchema` → `flowschema-flowcontrol-v1.json`). У yannh **немає** файлів з фрагментом `-k8s-io-` у назві — патерн `<group-з-крапками-як-дефіси>` дає 404.
717
717
  4. **Інакше** (CRD тощо) → [datreeio/CRDs-catalog](https://github.com/datreeio/CRDs-catalog). Типово для `$schema` у редакторі — **GitHub Pages**:
718
718
  `https://datreeio.github.io/CRDs-catalog/<group>/<kind>_<version>.json`
719
719
  (`<kind>` — лише літери та цифри в нижньому регістрі, без роздільників між CamelCase, як для yannh.)
@@ -32,6 +32,7 @@ export const AUTO_RULE_ORDER = Object.freeze([
32
32
  'capacitor',
33
33
  'changelog',
34
34
  'docker',
35
+ 'efes',
35
36
  'ga',
36
37
  'graphql',
37
38
  'hasura',
@@ -106,6 +107,7 @@ export const AUTO_RULE_DEPENDENCIES = Object.freeze(
106
107
  )
107
108
 
108
109
  const ABIE_REPOSITORY_URL_MARKER = 'https://github.com/abinbevefes/'
110
+ const EFES_REPOSITORY_URL_MARKER = 'https://github.com/efes-cloud/'
109
111
  const HASURA_CONFIG_MARKER = 'metadata_directory: metadata'
110
112
  const JS_LIKE_RE = /\.(?:mjs|cjs|js|jsx|ts|tsx)$/iu
111
113
  const REGO_RE = /\.rego$/iu
@@ -605,6 +607,7 @@ export async function detectAutoRules({
605
607
  : null
606
608
  )
607
609
  const isAbie = typeof repositoryUrl === 'string' && repositoryUrl.toLowerCase().includes(ABIE_REPOSITORY_URL_MARKER)
610
+ const isEfes = typeof repositoryUrl === 'string' && repositoryUrl.toLowerCase().includes(EFES_REPOSITORY_URL_MARKER)
608
611
  const depHits = await collectDependencyKeysPresentInPackageJsonTree(root, [
609
612
  'mssql',
610
613
  'pg',
@@ -639,6 +642,7 @@ export async function detectAutoRules({
639
642
  { enabled: packageJsonExists, id: 'bun' },
640
643
  { enabled: facts.hasCapacitorConfig, id: 'capacitor' },
641
644
  { enabled: facts.hasDockerfile, id: 'docker' },
645
+ { enabled: isEfes, id: 'efes' },
642
646
  { enabled: facts.hasGaWorkflowsDir, id: 'ga' },
643
647
  { enabled: facts.hasGqlTaggedTemplates, id: 'graphql' },
644
648
  { enabled: facts.hasHasuraConfig, id: 'hasura' },
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Синхронізує конфігурацію Claude Code (`.claude/settings.json`, `npm/CLAUDE.md`,
2
+ * Синхронізує конфігурацію Claude Code (`.claude/settings.json`,
3
3
  * slash-команди для checks, ADR Stop-hook) і Cursor hooks (`.cursor/hooks.json`)
4
4
  * у поточний проєкт із темплейтів пакету
5
5
  * `npm/.claude-template/`.
@@ -8,8 +8,6 @@
8
8
  * - `settings.json` — **merge**: користувацькі поля зберігаються; наші hooks
9
9
  * ідентифікуються командою-маркером (`MANAGED_HOOK_COMMAND_MARKERS`) і
10
10
  * перезаписуються; permissions.allow зливається через union (із дедублікацією).
11
- * - `npm/CLAUDE.md` — **fully owned**: завжди перезаписується; пропускається,
12
- * якщо в проєкті немає каталогу `npm/`.
13
11
  * - `.claude/commands/n-check.md` — fully owned slash-команда.
14
12
  * - `.claude/hooks/capture-decisions.sh` — fully owned bash-скрипт ADR capture Stop-hook;
15
13
  * копіюється з `.claude-template/hooks/`, лише коли в `.n-cursor.json` `rules`
@@ -52,7 +50,6 @@ const CURSOR_DIR = '.cursor'
52
50
  const CURSOR_HOOKS_FILE = `${CURSOR_DIR}/hooks.json`
53
51
  const ADR_HOOK_SCRIPT_NAME = 'capture-decisions.sh'
54
52
  const ADR_NORMALIZE_HOOK_SCRIPT_NAME = 'normalize-decisions.sh'
55
- const NPM_CLAUDE_MD_FILE = 'npm/CLAUDE.md'
56
53
  const TEMPLATE_DIR_NAME = '.claude-template'
57
54
 
58
55
  /** Канонічна група hooks для ADR capture Stop-hook'а — додається в settings, коли `adr` у `rules`. */
@@ -390,25 +387,6 @@ export function syncAdrNormalizeHookScript(projectRoot, templateDir) {
390
387
  return syncHookScript(projectRoot, templateDir, ADR_NORMALIZE_HOOK_SCRIPT_NAME)
391
388
  }
392
389
 
393
- /**
394
- * Копіює `npm/CLAUDE.md` з темплейту, якщо в проєкті є каталог `npm/`.
395
- * @param {string} projectRoot корінь проєкту, куди писати
396
- * @param {string} templateDir каталог `.claude-template/` усередині пакету `@nitra/cursor`
397
- * @returns {Promise<{ written: boolean, path: string }>} результат: чи писали файл, та його відносний шлях
398
- */
399
- export async function syncNpmClaudeMd(projectRoot, templateDir) {
400
- if (!existsSync(join(projectRoot, 'npm'))) {
401
- return { written: false, path: '' }
402
- }
403
- const templatePath = join(templateDir, 'npm-CLAUDE.md')
404
- if (!existsSync(templatePath)) {
405
- return { written: false, path: '' }
406
- }
407
- const content = await readFile(templatePath, 'utf8')
408
- await writeFile(join(projectRoot, NPM_CLAUDE_MD_FILE), content, 'utf8')
409
- return { written: true, path: NPM_CLAUDE_MD_FILE }
410
- }
411
-
412
390
  /**
413
391
  * Копіює всі slash-команди з `templateDir/commands/` у `.claude/commands/`.
414
392
  * Команди ідентифікуються тим, що вони лежать у темплейті — не перетинаються
@@ -444,14 +422,13 @@ export async function syncClaudeCommands(projectRoot, templateDir) {
444
422
  * @param {string} options.bundledPackageRoot корінь установленого `@nitra/cursor`
445
423
  * @param {boolean} options.enabled чи увімкнено sync (з `.n-cursor.json` `claude-config`)
446
424
  * @param {string[]} [options.rules] список увімкнених правил із `.n-cursor.json` — впливає на ADR Stop-hook (`adr`)
447
- * @returns {Promise<{ settings: boolean, cursorHooks: boolean, npmClaudeMd: boolean, commands: string[], adrHook: boolean, adrNormalizeHook: boolean }>} прапорці записів settings/CLAUDE.md/Cursor hooks/ADR-hook(s) та список записаних slash-команд
425
+ * @returns {Promise<{ settings: boolean, cursorHooks: boolean, commands: string[], adrHook: boolean, adrNormalizeHook: boolean }>} прапорці записів settings/Cursor hooks/ADR-hook(s) та список записаних slash-команд
448
426
  */
449
427
  export async function syncClaudeConfig({ projectRoot, bundledPackageRoot, enabled, rules = [] }) {
450
428
  if (!enabled) {
451
429
  return {
452
430
  settings: false,
453
431
  cursorHooks: false,
454
- npmClaudeMd: false,
455
432
  commands: [],
456
433
  adrHook: false,
457
434
  adrNormalizeHook: false
@@ -462,7 +439,6 @@ export async function syncClaudeConfig({ projectRoot, bundledPackageRoot, enable
462
439
  return {
463
440
  settings: false,
464
441
  cursorHooks: false,
465
- npmClaudeMd: false,
466
442
  commands: [],
467
443
  adrHook: false,
468
444
  adrNormalizeHook: false
@@ -475,12 +451,10 @@ export async function syncClaudeConfig({ projectRoot, bundledPackageRoot, enable
475
451
  : { written: false, path: '' }
476
452
  const settings = await syncClaudeSettings(projectRoot, templateDir, { includeAdrHook })
477
453
  const cursorHooks = await syncCursorHooksConfig(projectRoot, { includeAdrHook })
478
- const npmClaudeMd = await syncNpmClaudeMd(projectRoot, templateDir)
479
454
  const commands = await syncClaudeCommands(projectRoot, templateDir)
480
455
  return {
481
456
  settings: settings.written,
482
457
  cursorHooks: cursorHooks.written,
483
- npmClaudeMd: npmClaudeMd.written,
484
458
  commands,
485
459
  adrHook: adrHook.written,
486
460
  adrNormalizeHook: adrNormalizeHook.written
@@ -0,0 +1,185 @@
1
+ ---
2
+ name: n-efes-create-env
3
+ description: >-
4
+ Створення нового середовища (env) в репозиторії efes/manager — приймає назву
5
+ середовища як аргумент (наприклад `kz`, `kz-qa`, `tr-stage`, `ua-dev`).
6
+ Генерує .env.prod-<env>, .env.remote-<env>, оверлей site/k8s/<env>/,
7
+ додає скрипт start-remote-<env> у site/package.json і реєструє <env> у
8
+ списках branches GitHub Actions та Azure Pipelines. Якщо назва закінчується
9
+ на dev або -qa — non-production (база: md-qa); інакше — production (база: md).
10
+ Тригери: «створи середовище», «новий env», «add environment», «n-efes-create-env».
11
+ ---
12
+
13
+ # n-efes-create-env — створення нового середовища
14
+
15
+ Скіл генерує всі конфіги для нового середовища `manager`, спираючись на існуюче як шаблон. Запуск: `/n-efes-create-env <env>` або «створи середовище `<env>`».
16
+
17
+ ## Існуючі середовища (станом на створення скіла)
18
+
19
+ `dev` · `md` · `md-qa` · `tr` · `tr-qa`
20
+
21
+ ## Аргумент
22
+
23
+ Назва середовища — `$ARGUMENTS` (kebab-case, без пробілів). Якщо аргументу немає — спитай користувача.
24
+
25
+ ## Класифікація та джерело
26
+
27
+ | Закінчення | Тип | Базове середовище | Базовий домен |
28
+ | --------------- | -------------- | ----------------- | --------------------------- |
29
+ | `dev` або `-qa` | non-production | `md-qa` | `mayamd-qa.anadoluefes.com` |
30
+ | інше | production | `md` | `mayamd.anadoluefes.com` |
31
+
32
+ Перед роботою зафіксуй у себе:
33
+
34
+ - `ENV` — `$ARGUMENTS`
35
+ - `BASE` — `md-qa` або `md` згідно з таблицею вище
36
+ - `BASE_DOMAIN` — домен бази
37
+ - `DOMAIN` — `maya${ENV}.anadoluefes.com` (шаблон: префікс `maya` + env). Якщо ENV вже містить країну з дефісом (наприклад `kz-qa`) — домен буде `mayakz-qa.anadoluefes.com`. Якщо користувач хоче інший домен — підтверди.
38
+ - `COUNTRY` — країна без суфіксу `-qa`/`-dev`/`-stage` (наприклад `kz-qa` → `kz`). Потрібно для ACR-шляхів.
39
+
40
+ ## Кроки
41
+
42
+ ### 0. Перевірити, що середовище ще не існує
43
+
44
+ ```bash
45
+ test ! -f site/.env.prod-$ENV \
46
+ && test ! -f site/.env.remote-$ENV \
47
+ && test ! -d site/k8s/$ENV \
48
+ || { echo "Середовище $ENV вже існує — припини"; exit 1; }
49
+ ```
50
+
51
+ ### 1. Інтерактивне опитування — зібрати country-specific дані
52
+
53
+ **ОБОВ'ЯЗКОВО** перед будь-якими `cp`/`sed` запитай користувача через `AskUserQuestion` (у Cursor — звичайним повідомленням з варіантами). Не виконуй кроки 2–5, поки не отримав усі відповіді.
54
+
55
+ Запитай **одним викликом** `AskUserQuestion` із кількома запитаннями:
56
+
57
+ 1. **Тип середовища** — заголовок «Тип env»:
58
+ - «Нова країна» — env вводить нову країну (новий VITE_COUNTRY, своя SAP-tenant, свій бакет)
59
+ - «Новий етап існуючої країни» — env є додатковим етапом md/tr (інший суфікс, але та сама країна та tenant)
60
+
61
+ 2. **Домен** — заголовок «Domain»:
62
+ - `maya${ENV}.anadoluefes.com` (default, рекомендований)
63
+ - «Інший» — користувач введе власний
64
+
65
+ 3. **SAP-credentials** — заголовок «SAP auth»:
66
+ - «Залишити як у бази (`$BASE`)» — для нових етапів існуючої країни
67
+ - «Заглушки `TODO_SAP_*`» — для нової країни, реальні значення додасть devops/security окремим commit
68
+ - «Введу зараз» — користувач передасть значення в `Other` (формат: `ENDPOINT=…; CLIENT_ID=…; CLIENT_SECRET=…`)
69
+
70
+ 4. **Storage account (`VITE_BUCKET`)** — заголовок «Bucket»:
71
+ - «Залишити як у бази» — той самий storage account (`stmdmayasfaprod001`/`stmdmayasfadev001`)
72
+ - «Власний для нової країни» — користувач введе ім'я storage account в `Other` (наприклад `stkzmayasfaprod001`)
73
+
74
+ Якщо «Нова країна» — окремо (у тому ж або наступному виклику) запитай:
75
+
76
+ 5. **VITE_COUNTRY** — заголовок «Country»: `md`, `tr`, інше (через `Other`)
77
+ 6. **VITE_TFM_DEFAULT** — заголовок «TFM default»: `ru`, `en`, `tr`, `ro`, інше
78
+ 7. **VITE_TFM_LIST** — заголовок «TFM list»: набір популярних варіантів (`ru,en,ro,tr`, `en,tr`, `ru,en`) + `Other`
79
+
80
+ Збережи відповіді у змінні `DOMAIN`, `COUNTRY`, `TFM_DEFAULT`, `TFM_LIST`, `BUCKET_ACCOUNT`, `SAP_MODE` (`keep`/`stub`/`custom`), `SAP_VALUES` (якщо `custom`).
81
+
82
+ ### 2. Створити `.env.prod-$ENV` та `.env.remote-$ENV`
83
+
84
+ Скопіюй файли бази:
85
+
86
+ ```bash
87
+ cp site/.env.prod-$BASE site/.env.prod-$ENV
88
+ cp site/.env.remote-$BASE site/.env.remote-$ENV
89
+
90
+ # домен
91
+ sed -i '' "s|$BASE_DOMAIN|$DOMAIN|g" site/.env.prod-$ENV site/.env.remote-$ENV
92
+
93
+ # bucket path (maya-files-<base> → maya-files-$ENV)
94
+ sed -i '' "s|maya-files-$BASE|maya-files-$ENV|g" site/.env.prod-$ENV site/.env.remote-$ENV
95
+ ```
96
+
97
+ Далі **застосуй відповіді з кроку 1** (через `Edit`):
98
+
99
+ - Якщо `BUCKET_ACCOUNT` != base — заміни storage account host у `VITE_BUCKET`.
100
+ - Якщо тип = «Нова країна»:
101
+ - `VITE_COUNTRY=$COUNTRY`
102
+ - `VITE_TFM_DEFAULT=$TFM_DEFAULT`
103
+ - `VITE_TFM_LIST=$TFM_LIST`
104
+ - Якщо `SAP_MODE=stub` — заміни значення на:
105
+ - `VITE_SAP_AUTH_ENDPOINT=TODO_SAP_ENDPOINT`
106
+ - `VITE_SAP_AUTH_CLIENT_ID='TODO_SAP_CLIENT_ID'`
107
+ - `VITE_SAP_AUTH_CLIENT_SECRET=TODO_SAP_CLIENT_SECRET`
108
+ - Якщо `SAP_MODE=custom` — підстав `SAP_VALUES`.
109
+
110
+ Інваріанти, які мають лишитися після всіх правок:
111
+
112
+ - У `.env.remote-$ENV` — `VITE_DOMAIN=localhost`, `VITE_UPLOADER=/file-link/`, `VITE_EXPORT_EXCEL=/export-table/`.
113
+ - У `.env.prod-$ENV` — `VITE_DOMAIN=$DOMAIN`, `VITE_UPLOADER=https://$DOMAIN/file-link/`, `VITE_EXPORT_EXCEL=https://$DOMAIN/export-table/`.
114
+
115
+ ### 2. Створити `site/k8s/$ENV/kustomization.yaml`
116
+
117
+ ```bash
118
+ mkdir -p site/k8s/$ENV
119
+ cp site/k8s/$BASE/kustomization.yaml site/k8s/$ENV/kustomization.yaml
120
+ ```
121
+
122
+ Відредагуй новий файл:
123
+
124
+ - `namespace: $ENV`
125
+ - `images[].newName`:
126
+ - **production** → `aefes.azurecr.io/mayasfa-$ENV/$ENV/manager-site`
127
+ - **non-production** → `aefes.azurecr.io/mayasfa-$COUNTRY-dev/$ENV/manager-site`
128
+ - `HTTPRoute` патч → `hostnames: ["$DOMAIN"]`
129
+ - Для **production** залиш блок `components: [../components]` (HPA/PDB).
130
+ - Для **non-production** видали `components` блок і HPA/PDB-патчі (як у `md-qa`).
131
+
132
+ Перевір: запусти `kubectl kustomize site/k8s/$ENV --output /dev/null` (якщо `kubectl` доступний) — має пройти без помилок.
133
+
134
+ ### 3. Додати `start-remote-$ENV` у `site/package.json`
135
+
136
+ У секцію `"scripts"` додай рядок (зберігай порядок поряд із сусідніми `start-remote-*`):
137
+
138
+ ```json
139
+ "start-remote-$ENV": "vite dev --mode remote-$ENV",
140
+ ```
141
+
142
+ ### 4. Зареєструвати `$ENV` у CI/CD branch-списках
143
+
144
+ Додай `$ENV` у такі місця (зберігай існуючий порядок: dev → md-qa → md → tr → tr-qa → нові):
145
+
146
+ | Файл | Поле |
147
+ | ------------------------------------------- | ------------------------------ |
148
+ | `.github/workflows/sync-to-azure.yml` | `on.push.branches` |
149
+ | `.github/workflows/clean-merged-branch.yml` | `ignore_branches` (через кому) |
150
+ | `.azurepipelines/apply-k8s.yml` | `trigger.branches.include` |
151
+ | `.azurepipelines/site.yml` | `trigger.branches.include` |
152
+
153
+ Якщо існують інші `**/k8s/`-проекти у репозиторії — переконайся, що `$ENV` потрібен і там (на момент створення скіла є тільки `site/k8s/`).
154
+
155
+ ### 5. Попередження користувачу про зовнішні залежності
156
+
157
+ Скіл **не** створює ці артефакти — повідом про них користувача:
158
+
159
+ - У repo `MayaSFA/k8s` має існувати шаблон `.azurepipelines/azure-pipeline-templates/$ENV.yml` (його використовує `apply-k8s.yml` і `site.yml`).
160
+ - Гілка `$ENV` має бути створена в обох remote (GitHub + Azure DevOps).
161
+ - DNS-запис для `$DOMAIN` та health-check у gateway мають бути налаштовані відповідною командою.
162
+ - Якщо ENV — нова країна: ACR-репозиторій `mayasfa-$ENV` (для prod) або `mayasfa-$COUNTRY-dev` (для non-prod) має бути створений.
163
+
164
+ ### 6. Перевірка результату
165
+
166
+ ```bash
167
+ ls site/.env.prod-$ENV site/.env.remote-$ENV site/k8s/$ENV/kustomization.yaml
168
+ grep -n "$ENV" \
169
+ .github/workflows/sync-to-azure.yml \
170
+ .github/workflows/clean-merged-branch.yml \
171
+ .azurepipelines/apply-k8s.yml \
172
+ .azurepipelines/site.yml \
173
+ site/package.json
174
+ git status
175
+ ```
176
+
177
+ Виведи користувачу короткий звіт: що створено, що змінено, які зовнішні дії потрібні (з кроку 5). **Не комітити автоматично** — користувач сам перегляне через `git diff` і закомітить.
178
+
179
+ ## Нюанси та пастки
180
+
181
+ - **Доменний шаблон `maya${ENV}.anadoluefes.com`** працює для існуючих країн (md/tr). Якщо нова країна має інший публічний URL — підтверди в користувача _до_ запуску `sed`.
182
+ - **ACR-шлях суворо за шаблоном**: prod → `mayasfa-$ENV/$ENV/manager-site`, non-prod → `mayasfa-$COUNTRY-dev/$ENV/manager-site`. Жодних додаткових сегментів між ACR-namespace та `$ENV` бути не повинно.
183
+ - **`ENV=dev`**: гілка `dev` — спеціальний випадок (вживає `base/`, без оверлею). Скіл не призначений для перестворення `dev`.
184
+ - **`.env.development`** — лише для локального запуску без бекенду; скіл його не чіпає.
185
+ - **Не запускай `bun run lint` / `lint-ga`** в один потік з іншими — дивись CLAUDE.md «Лінт і ESLint». Перевір лише потрібний файл (`bunx eslint <path>` або точково).
@@ -0,0 +1 @@
1
+ [efes]