# Release Checklist (Հայերեն) 🌐 **Languages:** 🇺🇸 [English](../../../../ops/RELEASE_CHECKLIST.md) · 🇪🇹 [am](../../../am/docs/ops/RELEASE_CHECKLIST.md) · 🇸🇦 [ar](../../../ar/docs/ops/RELEASE_CHECKLIST.md) · 🇦🇿 [az](../../../az/docs/ops/RELEASE_CHECKLIST.md) · 🇧🇬 [bg](../../../bg/docs/ops/RELEASE_CHECKLIST.md) · 🇧🇩 [bn](../../../bn/docs/ops/RELEASE_CHECKLIST.md) · 🇧🇦 [bs](../../../bs/docs/ops/RELEASE_CHECKLIST.md) · 🇨🇿 [cs](../../../cs/docs/ops/RELEASE_CHECKLIST.md) · 🇩🇰 [da](../../../da/docs/ops/RELEASE_CHECKLIST.md) · 🇩🇪 [de](../../../de/docs/ops/RELEASE_CHECKLIST.md) · 🇬🇷 [el](../../../el/docs/ops/RELEASE_CHECKLIST.md) · 🇪🇸 [es](../../../es/docs/ops/RELEASE_CHECKLIST.md) · 🇪🇪 [et](../../../et/docs/ops/RELEASE_CHECKLIST.md) · 🇮🇷 [fa](../../../fa/docs/ops/RELEASE_CHECKLIST.md) · 🇫🇮 [fi](../../../fi/docs/ops/RELEASE_CHECKLIST.md) · 🇫🇷 [fr](../../../fr/docs/ops/RELEASE_CHECKLIST.md) · 🇮🇪 [ga](../../../ga/docs/ops/RELEASE_CHECKLIST.md) · 🇮🇳 [gu](../../../gu/docs/ops/RELEASE_CHECKLIST.md) · 🇳🇬 [ha](../../../ha/docs/ops/RELEASE_CHECKLIST.md) · 🇮🇱 [he](../../../he/docs/ops/RELEASE_CHECKLIST.md) · 🇮🇳 [hi](../../../hi/docs/ops/RELEASE_CHECKLIST.md) · 🇭🇷 [hr](../../../hr/docs/ops/RELEASE_CHECKLIST.md) · 🇭🇺 [hu](../../../hu/docs/ops/RELEASE_CHECKLIST.md) · 🇮🇩 [id](../../../id/docs/ops/RELEASE_CHECKLIST.md) · 🇳🇬 [ig](../../../ig/docs/ops/RELEASE_CHECKLIST.md) · 🇮🇹 [it](../../../it/docs/ops/RELEASE_CHECKLIST.md) · 🇯🇵 [ja](../../../ja/docs/ops/RELEASE_CHECKLIST.md) · 🇬🇪 [ka](../../../ka/docs/ops/RELEASE_CHECKLIST.md) · 🇰🇭 [km](../../../km/docs/ops/RELEASE_CHECKLIST.md) · 🇮🇳 [kn](../../../kn/docs/ops/RELEASE_CHECKLIST.md) · 🇰🇷 [ko](../../../ko/docs/ops/RELEASE_CHECKLIST.md) · 🇱🇹 [lt](../../../lt/docs/ops/RELEASE_CHECKLIST.md) · 🇱🇻 [lv](../../../lv/docs/ops/RELEASE_CHECKLIST.md) · 🇮🇳 [ml](../../../ml/docs/ops/RELEASE_CHECKLIST.md) · 🇮🇳 [mr](../../../mr/docs/ops/RELEASE_CHECKLIST.md) · 🇲🇾 [ms](../../../ms/docs/ops/RELEASE_CHECKLIST.md) · 🇲🇹 [mt](../../../mt/docs/ops/RELEASE_CHECKLIST.md) · 🇲🇲 [my](../../../my/docs/ops/RELEASE_CHECKLIST.md) · 🇳🇵 [ne](../../../ne/docs/ops/RELEASE_CHECKLIST.md) · 🇳🇱 [nl](../../../nl/docs/ops/RELEASE_CHECKLIST.md) · 🇳🇴 [no](../../../no/docs/ops/RELEASE_CHECKLIST.md) · 🇮🇳 [or](../../../or/docs/ops/RELEASE_CHECKLIST.md) · 🇮🇳 [pa](../../../pa/docs/ops/RELEASE_CHECKLIST.md) · 🇵🇭 [phi](../../../phi/docs/ops/RELEASE_CHECKLIST.md) · 🇵🇱 [pl](../../../pl/docs/ops/RELEASE_CHECKLIST.md) · 🇵🇹 [pt](../../../pt/docs/ops/RELEASE_CHECKLIST.md) · 🇧🇷 [pt-BR](../../../pt-BR/docs/ops/RELEASE_CHECKLIST.md) · 🇷🇴 [ro](../../../ro/docs/ops/RELEASE_CHECKLIST.md) · 🇷🇺 [ru](../../../ru/docs/ops/RELEASE_CHECKLIST.md) · 🇱🇰 [si](../../../si/docs/ops/RELEASE_CHECKLIST.md) · 🇸🇰 [sk](../../../sk/docs/ops/RELEASE_CHECKLIST.md) · 🇸🇮 [sl](../../../sl/docs/ops/RELEASE_CHECKLIST.md) · 🇷🇸 [sr](../../../sr/docs/ops/RELEASE_CHECKLIST.md) · 🇸🇪 [sv](../../../sv/docs/ops/RELEASE_CHECKLIST.md) · 🇰🇪 [sw](../../../sw/docs/ops/RELEASE_CHECKLIST.md) · 🇮🇳 [ta](../../../ta/docs/ops/RELEASE_CHECKLIST.md) · 🇮🇳 [te](../../../te/docs/ops/RELEASE_CHECKLIST.md) · 🇹🇭 [th](../../../th/docs/ops/RELEASE_CHECKLIST.md) · 🇹🇷 [tr](../../../tr/docs/ops/RELEASE_CHECKLIST.md) · 🇺🇦 [uk-UA](../../../uk-UA/docs/ops/RELEASE_CHECKLIST.md) · 🇵🇰 [ur](../../../ur/docs/ops/RELEASE_CHECKLIST.md) · 🇺🇿 [uz](../../../uz/docs/ops/RELEASE_CHECKLIST.md) · 🇻🇳 [vi](../../../vi/docs/ops/RELEASE_CHECKLIST.md) · 🇳🇬 [yo](../../../yo/docs/ops/RELEASE_CHECKLIST.md) · 🇨🇳 [zh-CN](../../../zh-CN/docs/ops/RELEASE_CHECKLIST.md) · 🇹🇼 [zh-TW](../../../zh-TW/docs/ops/RELEASE_CHECKLIST.md) --- > **Վերջին թարմացումը՝** 2026-08-28 — v3.8.51 > Պարզեցված թողարկման գործընթաց, որն ավտոմատացման համար օգտագործում է Claude Code-ի հմտությունները։ > > **Թողարկումների միջև հերթը/ճյուղը պահեք անխափան վիճակում՝** տե՛ս [RELEASE_GREEN.md](./RELEASE_GREEN.md) > (`/green-prs` հրամանների ընտանիք + `npm run check:release-green` + `/babysit` + գիշերային գործարկում)։ Սա պարբերաբար, և հատկապես այս ստուգաթերթից **առաջ**, գործարկելը նպաստում է, որ թողարկման PR-ը սկզբից իսկ լինի անխափան վիճակում։ ## Կարճ ամփոփում ```bash # 1. Բարձրացրեք տարբերակը + ստեղծեք CHANGELOG (հմտություն) /version-bump-cc patch # կամ minor/major # 2. Տեղային միջավայրում գործարկեք որակի ստուգումը npm run check # lint + թեստեր npm run test:coverage # ծածկույթի ամբողջական շեմ (60/60/60/60) # 3. Կառուցեք և կատարեք նախնական ստուգում npm run build npm run test:e2e # ոչ պարտադիր, բայց խորհուրդ է տրվում # 4. Ստեղծեք թողարկումը (հմտություն) /generate-release-cc # 5. Տեղակայեք (հմտություն) /deploy-vps-both-cc # կամ akamai-cc / local-cc # 6. Հավաքեք թողարկման ապացույցները (հմտություն) /capture-release-evidences-cc ``` ## npm Trusted Publishing (լռելյայն՝ սկսած v3.8.51-ից) — ըստ պահանջի՝ փուլային, որպես պահուստային տարբերակ՝ ուղղակի `npm-publish.yml`-ը լռելյայն հրապարակում է **npm Trusted Publishing (OIDC)**-ի միջոցով․ `stage-npm` առաջադրանքը (github-hosted) տվյալ գործարկման համար GitHub-ի id-token-ը փոխանակում է կարճաժամկետ npm հավատարմագրի հետ՝ առանց պահոցային գաղտնիքներում երկարաժամկետ npm նշան պահելու, առանց 2FA հարցման և կցված ծագման ապացույցով։ Սա npm-ի կողմից այժմ թույլատրված շրջանցումն է, քանի որ 2FA-ն բաց թողնող նշանները հանվում են շրջանառությունից․ այն վերականգնում է մինչև v3.8.48-ը նախագծում գործող ամբողջովին ավտոմատ հոսքը՝ միաժամանակ պահպանելով WS1.3 երաշխիքը (արտահոսած նշանը չի կարող ինքնուրույն հրապարակել, քանի որ նշան գոյություն չունի)։ **Մեկանգամյա կարգավորում (սեփականատեր)․** npmjs.com → `omniroute` փաթեթ → Settings → _Trusted Publisher_ → GitHub: owner `diegosouzapw`, repo `OmniRoute`, workflow `npm-publish.yml` (environment: none)։ Մինչև դրա առկայությունը ավտոմատ քայլը ձախողվում է `ENEEDAUTH`-ով․ կրկին գործարկեք `publish_mode=staged`-ով (ստորև) կամ `direct`-ով։ ### Փուլային հրապարակում (ըստ պահանջի՝ `publish_mode=staged`) npm-publish աշխատանքային հոսքն այլևս ուղղակիորեն չի հրապարակում․ այն գործարկում է փաթեթավորված tarball-ը (`check:pack-boot`), ապա կատարում `npm stage publish`․ ռեեստրում պահվում են հենց այդ բայթերը, որոնք **հնարավոր չէ տեղադրել**, մինչև սեփականատերը չհաստատի։ Մարդու մասնակցությամբ 2FA սահմանակետը տեղափոխվել է ապացուցումից ՀԵՏՈ, ոչ թե դրանից առաջ։ **Սեփականատիրոջ գործողությունները աշխատանքային հոսքի հաջող ավարտից հետո․** 1. `npm stage list omniroute` — գտեք փուլի id-ն (այն նաև ցուցադրվում է աշխատանքային հոսքի ամփոփագրում)։ 2. Ստուգեք փուլային բայթերը (խորհուրդ է տրվում)․ `npm stage download `, ապա ներբեռնված tarball-ը տեղադրեք ժամանակավոր prefix-ում և գործարկեք այն (`npm run check:pack-boot`-ը CI-ում ավտոմատացնում է նույն pack→install→boot ստուգման արդյունքը)։ 3. `npm stage approve ` — 2FA հարցումն ԻՆՔՆԻՆ հրապարակումն է։ `npm stage reject `-ը չեղարկում է այն։ 4. Հրապարակումից հետո անվտանգության ցանց․ հրապարակումից հետո ստուգիչը (v3.8.49 ծրագրի WS1.4) մաքուր կոնտեյներում հանրային ռեեստրից տեղադրում և գործարկում է հրապարակված տարբերակը։ **Արտակարգ պահուստային տարբերակ․** `workflow_dispatch`-ը `publish_mode=direct`-ով վերականգնում է ժառանգված անմիջական `npm publish`-ը (օգտագործեք միայն այն դեպքում, երբ փուլային հրապարակումն ինքն է սխալ աշխատում, և գրանցեք պատճառը)։ **Մեկանգամյա խստացում (սեփականատեր, npmjs.com)․** `omniroute`-ի համար կազմաձևեք Trusted Publisher-ը միայն փուլային ռեժիմով, որպեսզի արտահոսած երկարաժամկետ նշանը չկարողանա որևէ տեղից ուղղակիորեն կատարել `npm publish`․ CI-ն կարող է միայն փուլային հրապարակում կատարել, իսկ թողարկումը կարող է իրականացնել միայն սեփականատիրոջ 2FA-ն։ **Խափանված արտեֆակտի ընթացակարգ (անփոփոխ)․** որպես լռելյայն առաջին քայլ օգտագործեք `npm deprecate omniroute@ " — use "` (տևում է րոպեներ, հետադարձելի է)․ `npm unpublish` օգտագործեք միայն 72-ժամյա/կախյալներ չունենալու պատուհանում և երբեք՝ որպես առաջին քայլ։ Docker․ երբեք մի վերագրեք տարբերակի թեգը․ հետադարձ անցումը `latest`-ը վերջին ճիշտ digest-ին վերաուղղելն է։ **Docker Hub-ի `latest` (պարտադիր յուրաքանչյուր կայուն SemVer հրապարակման դեպքում)․** `docker-publish` աշխատանքային հոսքը պետք է թեգավորի **և՛** `X.Y.Z`-ը, **և՛**, երբ `should-promote-latest.sh`-ը հաստատում է, որ սա ամենաբարձր կայուն SemVer-ն է, `:latest`-ը՝ **նույն digest**-ով։ Առաջադրանքից հետո Hub-ի `latest` digest-ը պետք է հավասար լինի նոր SemVer digest-ին, իսկ `last_updated`-ը՝ թարմացված լինի։ Մի թողեք `:latest`-ը հին կառուցման վրա, երբ թողարկման նշումներում խոսվում է ուղղումների մասին, որոնք առկա են միայն git-ում։ Compose-ի արագ մեկնարկներն օգտագործում են `:latest`, իսկ GitOps-ը պետք է շարունակի ամրագրել `X.Y.Z`-ը։ Տե՛ս [Docker-ի թողարկման ալիքներ](../guides/DOCKER_GUIDE.md#release-channels) և #10317։ ## Թեժ ուղղումների արագ ուղի (`hotfix` պիտակ) `hotfix` պիտակով PR-ը բաց է թողնում CI-ի ծանր մատրիցը (9 հատվածով E2E, ծածկույթի շեմի աստիճանական բարձրացում, quality-gate, quality-extended) և պահպանում արագ, բարձր ազդանշանային ստուգումները՝ build, unit հատվածներ, integration, vitest, lint/typecheck, docs-sync, `check:pack-artifact` և tarball-ի մեկնարկային smoke ստուգումը (`check:pack-boot`)։ Նպատակ՝ կանաչ կարգավիճակ ≤15 րոպեում՝ ~33 րոպեի փոխարեն։ **Մուտքի քաղաքականություն — բոլոր չորս պայմանները պարտադիր են (Chromium/VS Code/Node արտակարգ ուղիների օրինակով).** 1. **Կրիտիկականություն**. արտադրական միջավայրը խափանված է՝ հրապարակված artifact-ը խափանվում է մեկնարկի ժամանակ / անվտանգության ուղղում է / թողարկման յուրաքանչյուր օգտատեր տուժում է։ «Կարևոր»-ը դեռ «խափանված» չէ։ 2. **Լիազորություն**. միայն repository-ի սեփականատերն է կիրառում `hotfix` պիտակը։ Պիտակն ԻՆՔՆԻՆ հաստատումն է՝ երբեք ինքնուրույն մի կիրառեք campaign PR-ի վրա։ 3. **Ապացույց**. PR-ի նկարագրությունը հղում է նախորդ՝ ամբողջությամբ կանաչ ծանր գործարկմանը (այն փաթեթին, որը բաց թողնված job-երը կվերավավերացնեին), ինչպես նաև տվյալ ուղղման՝ սկզբում ձախողվող, ապա հաջող անցնող թեստին։ 4. **Ծավալ**. միայն cherry-pick՝ նվազագույն ուղղում, առանց վերակառուցումների և կողմնակի փոփոխությունների։ Բաց թողնված coverage/ratchet մակերեսը վերավավերացվում է release ճյուղի հաջորդ ամբողջական գործարկմամբ (շարունակական release-green). ուղին բաց է թողնում միայն ՍՊԱՍՈՒՄԸ, ոչ երբեք վավերացումը։ Միայն թեստեր պարունակող փոփոխությունները (բոլոր ֆայլերը՝ `tests/`-ի ներքո, ոչ մեկը՝ `tests/e2e/`-ի ներքո) ավտոմատ բաց են թողնում E2E մատրիցը՝ առանց որևէ պիտակի։ ## Մանրամասն ստուգաթերթ ### Թողարկումից առաջ - [ ] Այս թողարկմանը նպատակաուղղված բոլոր PR-երը միավորված են `release/vX.Y.0` ճյուղին - [ ] Այս տարբերակի համար բոլոր բաց Linear/issue տարրերը փակված են կամ տեղափոխված հաջորդ հանգրվան - [ ] CI-ն կանաչ է `release/vX.Y.0` ճյուղում - [ ] Կոդում `TODO(release)` նշիչներ չկան՝ `grep -r "TODO(release)" src/ open-sse/` - [ ] Docker-ի բազային image-ը արդիական է (ներկայում՝ `node:24.15.0-trixie-slim`) ### Տարբերակ և փոփոխությունների մատյան - [ ] Գործարկել `/version-bump-cc `-ը (Claude Code skill) - Թարմացնում է տարբերակը `package.json`, `electron/package.json` ֆայլերում - Վերագեներացնում է `CHANGELOG.md`-ը՝ վերջին tag-ից ի վեր git commit-ների հիման վրա - Թարմացնում է README.md-ի badge-երը - [ ] Ձեռքով վերանայել CHANGELOG.md-ը և անհրաժեշտության դեպքում մաքրել commit-ների հաղորդագրությունները - [ ] Համոզվել, որ `CHANGELOG.md`-ի վերջին semver բաժինը համապատասխանում է `package.json`-ի տարբերակին - [ ] Առաջիկա աշխատանքի համար `## [Unreleased]`-ը պահել որպես փոփոխությունների մատյանի առաջին բաժին - [ ] Թարմացնել `docs/openapi.yaml` → `info.version`-ը պետք է համապատասխանի `package.json`-ի տարբերակին ### Կոդի որակ - [ ] `npm run lint` — 0 սխալ (նախազգուշացումները նախկինում առկա են եղել) - [ ] `npm run typecheck:core` — անթերի - [ ] `npm run typecheck:noimplicit:core` — անթերի (խիստ) - [ ] `npm run check:cycles` — շրջանաձև կախվածություններ չկան - [ ] `npm run check:any-budget:t11` — բյուջեի սահմաններում - [ ] `npm run check:route-validation:t06` — անթերի - [ ] `npm run check:node-runtime` — աջակցվող runtime-ի նվազագույն սահմանը պահպանված է (`>=22.22.2 <23`, `>=24.0.0 <27`, ըստ `src/shared/utils/nodeRuntimeSupport.ts`-ի `SUPPORTED_NODE_RANGE`-ի՝ համապատասխանեցված `package.json`-ի `engines`-ին) ### Թեստավորում - [ ] `npm run test:unit` — հաջող - [ ] `npm run test:vitest` — հաջող (MCP server, autoCombo, cache) - [ ] `npm run test:coverage` — 60/60/60/60 շեմը բավարարված է (հրահանգներ/տողեր/ֆունկցիաներ/ճյուղեր) - [ ] `npm run test:integration` — հաջող (եթե փոփոխություններն առնչվում են DB-ին / handler-ներին) - [ ] `npm run test:combo:matrix` — հաջող (combo ռազմավարությունների մատրից. որոշակիորեն ապացուցում է բոլոր 19 հրապարակային routing ռազմավարությունների ընտրության որոշումները. գործարկել combo routing-ին, ռազմավարության որոշմանը կամ fallback տրամաբանությանը վերաբերող փոփոխությունների դեպքում) - [ ] `RUN_COMBO_LIVE=1 npm run test:combo:live` — **ընտրովի/ձեռքով** (պայմանով կառավարվող իրական upstream smoke ստուգում. VPS-ի `root@192.168.0.15` հասցեից վերցնում է միայն ընթերցման համար նախատեսված DB snapshot, դիմում է իրական մատակարարներին, ծախսում է կրեդիտներ, երբեք չի գործարկվում CI-ում, առանց պայմանը միացնելու՝ մաքուր կերպով բաց է թողնվում) - [ ] `npm run test:combo:live:vps` — **ընտրովի/ձեռքով** (Phase-3 VPS կենդանի smoke ստուգում. 7 HTTP սցենար կենդանի `.15` server-ի նկատմամբ՝ պարզ Node ESM-ի միջոցով. պահանջում է `ssh root@192.168.0.15`, ստեղծում/ջնջում է միայն `__live_test__*` combo-ներ, դիմում է իրական մատակարարներին, երբեք չի գործարկվում CI-ում) - [ ] `npm run test:e2e` — հաջող (UI փոփոխություններ) - [ ] `npm run test:protocols:e2e` — հաջող (MCP/A2A փոփոխություններ) - [ ] `npm run test:ecosystem` — հաջող ### Hook-եր (վավերացված Husky-ով) Husky hook-երը գտնվում են `.husky/`-ում և ավտոմատ գործարկվում են git գործողությունների ժամանակ։ - **pre-commit:** `npx lint-staged + node scripts/check/check-docs-sync.mjs + npm run check:any-budget:t11` - **pre-push:** արագ և որոշակի ստուգումներ՝ `npm run check:any-budget:t11 && npm run check:tracked-artifacts` (ակտիվացված՝ 2026-06-13)։ Դիտավորյալ չի ներառում `test:unit`-ը (դանդաղ է, ծածկվում է CI-ի `test-unit` job-ով)։ - Release ճյուղերը push անելուց առաջ ձեռքով գործարկել `npm run test:unit`։ Եթե hook-ը ձախողվում է՝ ուղղեք հիմքում ընկած խնդիրը, մի շրջանցեք այն `--no-verify`-ով։ ### Conventional Commits Թողարկմանը ներառվող բոլոր commit-ները պետք է հետևեն `type(scope): subject` ձևաչափին։ **Վավեր type-եր.** `feat`, `fix`, `refactor`, `docs`, `test`, `chore`, `perf`, `style`, `ci` **Վավեր scope-եր.** `db`, `sse`, `oauth`, `dashboard`, `api`, `cli`, `docker`, `ci`, `mcp`, `a2a`, `memory`, `skills`, `cloud-agent`, `guardrails`, `compression`, `auto-combo`, `resilience`, `providers`, `executors`, `translator`, `domain`, `authz` Հետադարձ համատեղելիությունը խախտող փոփոխություններ. ավելացնել `BREAKING CHANGE:` վերջնամասը կամ scope-ից հետո `!` (օրինակ՝ `feat(api)!: drop /v0`)։ ### Փաստաթղթավորում - [ ] `npm run check:docs-sync`-ը հաջողությամբ է անցնում (ավտոմատ գործարկվում է pre-commit-ի միջոցով) - [ ] `npm run check:docs-all`-ը հաջողությամբ է անցնում (ընդհանուր ստուգում՝ docs-sync + docs-counts + env-doc-sync + deprecated-versions + doc-links) - [ ] `npm run check:env-doc-sync`-ն ավարտվում է 0 կոդով — կոդ ↔ `.env.example` ↔ `docs/reference/ENVIRONMENT.md` միջավայրի պայմանագիրը պահպանված է - [ ] `npm run check:doc-links`-ն ավարտվում է 0 կոդով — վերակառուցումից հետո ներքին markdown հղումները կոտրված չեն - [ ] `docs/architecture/ARCHITECTURE.md`-ը վերանայված է պահեստավորման/կատարման միջավայրի շեղումների առումով - [ ] `docs/guides/TROUBLESHOOTING.md`-ը վերանայված է միջավայրի փոփոխականների և գործառնական շեղումների առումով - [ ] Եթե `.env.example`-ը փոխվել է՝ `docs/reference/ENVIRONMENT.md`-ը թարմացված է - [ ] Եթե նոր հնարավորությունն ունի UI՝ այն նշված է `docs/guides/USER_GUIDE.md`-ում - [ ] Եթե նոր հնարավորությունն ունի API՝ `docs/reference/API_REFERENCE.md`-ը և `docs/openapi.yaml`-ը թարմացված են - [ ] Եթե նոր հնարավորությունը մոդուլ է՝ առկա է առանձին `docs/.md` - [ ] Եթե փոփոխությունը համատեղելիությունը խախտող է՝ `docs/guides/TROUBLESHOOTING.md`-ում կա միգրացիայի մասին նշում ### i18n - [ ] `npm run i18n:check`-ն ավարտվում է 0 կոդով — թարգմանության վիճակը (`.i18n-state.json`) համաժամեցված է սկզբնաղբյուր փաստաթղթերի հետ (խիստ ռեժիմում շեղված սկզբնաղբյուրներ չկան․ զգուշացման ռեժիմի խորհրդատվական հաղորդագրություններն ընդունելի են փաստաթղթերի վերջին րոպեի շտկումների համար, սակայն մինչև պիտակավորումը արդյունքը պետք է լինի 0) - [ ] `npm run i18n:check-ui-coverage`-ն ավարտվում է 0 կոդով — UI-ի յուրաքանչյուր տեղայնացում ունի առնվազն 80% ծածկույթ - [ ] `npm run i18n:sync-ui:dry`-ը բոլոր 42 տեղայնացումների համար հաղորդում է 0 բացակայող բանալի - [ ] Եթե սկզբնաղբյուր անգլերեն փաստաթղթերը փոխվել են, նախքան պիտակավորումը գործարկեք `npm run i18n:run` (պահանջում է `OMNIROUTE_TRANSLATION_API_KEY`՝ `.env`-ում) - [ ] Թարգմանության ներդրումները, եթե աննշան են, կարելի է հետաձգել մինչև հաջորդ թողարկումը (հետևել CHANGELOG-ում) ### Տվյալների բազայի միգրացիաներ - [ ] Եթե `src/lib/db/migrations/`-ում նոր ֆայլեր կան՝ - [ ] Յուրաքանչյուր միգրացիա իդեմպոտենտ է (`CREATE TABLE IF NOT EXISTS` և այլն) - [ ] Միգրացիաները ներառված են տրանզակցիաների մեջ - [ ] Համարակալումը ճիշտ է (հաջորդականության մեջ բացեր չկան) - [ ] Փորձարկեք նոր տեղադրման դեպքում՝ ջնջեք `~/.omniroute/omniroute.db`-ը և գործարկեք `npm run dev` - [ ] Փորձարկեք գոյություն ունեցող տեղադրման դեպքում՝ պահուստավորեք DB-ն, գործարկեք միգրացիան և ստուգեք սխեման - [ ] Եթե միգրացիան վերագրում է աղյուսակները, համոզվեք, որ WAL ֆայլերը (`-wal`, `-shm`) ճիշտ են մշակվում ### Մատակարարների կատալոգ (վավերացված Zod-ով) - [ ] `src/shared/constants/providers.ts`-ի Zod սխեման բեռնման պահին վավեր է - [ ] Բոլոր մատակարարներն ունեն պարտադիր դաշտերը (`id`, `label`, `kind` և այլն) - [ ] Նոր անվճար մատակարարների համար տրամադրված է `freeNote` - [ ] OAuth մատակարարների `oauthConfig`-ը գրանցված է `src/lib/oauth/constants/oauth.ts`-ում - [ ] Եթե նոր մատակարար է ավելացվել՝ համապատասխան կատարիչը գտնվում է `open-sse/executors/`-ում - [ ] Եթե ձևաչափը OpenAI-ինը չէ՝ թարգմանիչը գտնվում է `open-sse/translator/`-ում - [ ] Մոդելները գրանցված են `open-sse/config/providerRegistry.ts`-ում - [ ] `tests/unit/`-ի միավորային թեստերը ծածկում են մատակարարների դասակարգումն ու երթուղավորումը ### Աշխատասեղանային հավելված (Electron) Եթե `electron/`-ը փոխվել է՝ - [ ] `npm run electron:smoke:packaged`-ը հաջողությամբ է անցնում - [ ] Կառուցումները փորձարկված են `:win`, `:mac`, `:linux` տարբերակներից առնվազն մեկի համար - [ ] Կոդի ստորագրման վկայագրերի ժամկետը լրացած չէ (եթե ստորագրում է կատարվում) - [ ] `electron/package.json`-ի տարբերակը համընկնում է արմատային `package.json`-ի տարբերակին - [ ] Եթե թողարկումը կատարվում է `stable` ալիքում, ավտոմատ թարմացման ալիքի ցուցիչը թարմացված է ### Կառուցման դասավորություն Շտեմարանն օգտագործում է ելքային երեք առանձին գրացուցակ — երբեք մի խառնեք դրանք․ | Գրացուցակ | Նպատակ | Հետագծվո՞ւմ է | | --------- | --------------------------------------------------------------------- | --------------- | | `src/` | Հավելվածի սկզբնաղբյուր (TypeScript / TSX) | Այո | | `.build/` | Կառուցման միջանկյալ նյութեր — `next build`-ի ելք (`distDir`) | Ոչ (gitignored) | | `dist/` | Առաքման ենթակա npm փաթեթ — հավաքվում է `assembleStandalone`-ի միջոցով | Ոչ (gitignored) | > **Օպերատորի նշում․** հեռակա VPS պատկերի գրացուցակը մնում է `/usr/lib/node_modules/omniroute/app/`։ > Փոխվել է միայն շտեմարանի **ներսում գտնվող** կառուցման ելքը (`app/` → `dist/`)։ Տեղակայման հմտությունները rsync-ի միջոցով > `dist/`-ի բովանդակությունը փոխանցում են հեռակա `app/` գրացուցակ — VPS-ի ուղիները փոխելու կարիք չկա։ **Մեկ կառուցմամբ ընթացք․** ``` npm run build:release └─ rm -rf .build dist (մաքրում) └─ next build → .build/next/ (միջանկյալ նյութեր) └─ assembleStandalone (ինքնուրույն տարբերակը + static + public + բնիկ բաղադրիչները պատճենում է dist/) └─ գրում է dist/BUILD_SHA (HEAD հսկիչ արժեք) ``` Տեղակայման համար ՄԻ՛ գործարկեք `npm run build`, ապա առանձին `npm run build:cli` — օգտագործեք `npm run build:release`, որը մեկ հրամանով կատարում է մաքուր վերակառուցում և ստեղծում հսկիչ արժեքը։ ### Արտեֆակտի վավերացում - [ ] `npm run build:release`-ը հաջողվում է, և `dist/BUILD_SHA` == `git rev-parse --short HEAD` - [ ] `npm run check:pack-artifact`-ը մաքուր է — չկան `app.__qa_backup`, `scripts/scratch`, `package-lock.json` կամ այլ տեղային մնացորդներ - [ ] Կառուցումից հետո `dist/server.js`-ը գոյություն ունի ### Պիտակավորում և թողարկում - [ ] Գործարկեք `/generate-release-cc`-ը (Claude Code-ի հմտություն)՝ - Ստեղծում է `vX.Y.Z` պիտակը - Ուղարկում է պիտակը և ճյուղը - Բացում է GitHub Release՝ փոփոխությունների մատյանի բովանդակությամբ - Կցում է Electron-ի տեղադրիչները (եթե կառուցվել են) - [ ] Կամ ձեռքով՝ ```bash git tag -a vX.Y.Z -m "Release vX.Y.Z" git push origin vX.Y.Z gh release create vX.Y.Z --notes-from-tag ``` ### Տեղակայում Տեղակայման հմտություններն օգտագործում են թեթև rsync ընթացքը — առանց `npm pack`-ի և `npm i -g`-ի․ - [ ] Օգտագործեք նպատակային միջավայրին համապատասխանող տեղակայման հմտությունը՝ - `/deploy-vps-local-cc` — տեղային VPS (192.168.0.15) - `/deploy-vps-akamai-cc` — Akamai VPS (69.164.221.35) - `/deploy-vps-both-cc` — երկուսն էլ - [ ] Տեղակայումից առաջ հաստատեք, որ `dist/BUILD_SHA` == `git rev-parse --short HEAD` - [ ] Կառուցումը պետք է կատարվի այնտեղ, որտեղ `node_modules`-ն իրական է (հիմնական աշխատանքային պատճենում կամ `npm ci` գործարկված worktree-ում — ՈՉ թե սիմվոլիկ հղումով worktree-ում) - [ ] Կատարեք տեղակայված օրինակի ծխային փորձարկում՝ - Բացեք `/dashboard/health` → ստուգեք, որ տարբերակի տողը համապատասխանում է թողարկմանը - Հայտնի մատակարարի նկատմամբ կատարեք `/v1/chat/completions` հարցում - Ստուգեք, որ `/api/monitoring/health`-ը վերադարձնում է `CLOSED` վիճակով շղթայի անջատիչներ - Հաստատեք, որ MCP փոխադրամիջոցները պատասխանում են (`/mcp` HTTP, `/mcp-sse` SSE) ### Թողարկումից հետո - [ ] Գործարկել `/capture-release-evidences-cc`-ը (Claude Code-ի հմտություն) - Նոր գործառույթների WebP էկրանակադրերի/տեսագրությունների ստացում - Կցում է թողարկման նշումներին / բլոգային գրառմանը - [ ] Թարմացնել GitHub Discussions-ը / Discord-ը՝ թողարկման հայտարարությամբ - [ ] Բացել հաջորդ տարբերակի milestone-ը - [ ] Եթե կրիտիկական է՝ ամրացնել քննարկումը կամ հրապարակել `news.json`-ում՝ հավելվածի ներսում ցուցադրվող բանների համար ### Radar-ի հրապարակային գործարկման անցակետ Radar-ի հայտարարությունը միտումնավոր commit է արված `active: false` արժեքով։ Ակտիվացումն առանձին փոփոխություն է, որը կատարվում է ստորև նշված յուրաքանչյուր կետի ապացուցումից հետո․ - [ ] Radar-ի բոլոր շարված PR-ները միավորված են, իսկ release-tip CI-ն հաջող է ավարտվել - [ ] Տեղակայել և smoke թեստավորել OSS Radar-ի route-երը՝ `RADAR_ENABLED`-ը լռելյայն անջատված պահելով - [ ] Smoke թեստավորել `GET /planos`, `/termos`, `/privacidade` և `/reembolso` հասցեները նշված Radar host-ում - [ ] Մասնավոր ծառայությունում գրանցել օպերատորի ինքնությունը/կոնտակտային տվյալները/հասցեն և սեփականատիրոջ կողմից հաստատված իրավական ստուգումը - [ ] Stripe Checkout-ը և ստորագրված webhook-ը փորձարկել միայն թեստային ռեժիմում - [ ] Փորձարկել մեկ գաղտնագրված տրանզակցիոն էլփոստի առաքում՝ հաստատված ուղարկողով/դոմենով - [ ] Ապացուցել պահուստային պատճենից վերականգնումը և վերահսկվող, բյուջետային սահմանաչափով մեկ հետազոտական գործարկումը - [ ] Հաստատել BRL/PIX-ի վերանայման քաղաքականությունը՝ նախքան նվիրատվության ապացույց ընդունելը - [ ] Հրապարակային Checkout-ը միացնել միայն նախորդ անցակետերը հաղթահարելուց հետո, ապա ակտիվացնել `news.json`-ի նոր ID-ն - [ ] Ստուգել, որ գլխավոր էջի բաններն օգտագործում է տեղայնացված տեքստ, և նոր ID-ն կրկին հայտնվում է ավելի հին ID-ն փակելուց հետո ## Ներկառուցված ծառայությունների smoke ստուգում (v3.8.4+) Ներկառուցված ծառայությունների փոփոխություններ ներառող որևէ թողարկում հրապարակելուց առաջ ստուգեք՝ ### Մաքուր DB-ով մեկնարկ (հայտնաբերում է միգրացիաների բախումները՝ ավելացվել է v3.8.4-ի հրատապ ուղղումից հետո) - [ ] `DATA_DIR=$(mktemp -d) npm start &` — սպասեք 10 վրկ․ մեկնարկին - [ ] `curl -s http://127.0.0.1:20128/api/services/9router/status | jq '.tool'` վերադարձնում է `"9router"` (ՈՉ 404, ՈՉ 500)։ Հաստատում է, որ `071_services.sql` միգրացիան կիրառվել է, և տողը սկզբնարժեքավորվել է։ - [ ] `sqlite3 $DATA_DIR/storage.sqlite "PRAGMA table_info(version_manager);" | grep -E "provider_expose|logs_buffer_path|last_sync_at"` վերադարձնում է 3 տող։ - [ ] `sqlite3 $DATA_DIR/storage.sqlite "PRAGMA table_info(webhooks);" | grep -E "kind|metadata_encrypted"` վերադարձնում է 2 տող (հաստատում է, որ `070_webhooks_kind_metadata.sql` միգրացիան կիրառվել է)։ - [ ] `node --import tsx/esm --test tests/unit/db/no-migration-collisions.test.ts` հաջողությամբ է անցնում՝ պաշտպանելով ապագա բախումներից։ ### 9Router - [ ] `POST /api/services/9router/install`-ը 2 րոպեից պակաս ժամանակում վերադարձնում է 200՝ `installedVersion`-ով - [ ] `POST /api/services/9router/start`-ը 30 վրկ․-ից պակաս ժամանակում վերադարձնում է 200 և `state: "running"` - [ ] `GET /api/services/9router/status`-ը հաղորդում է `health: "healthy"` - [ ] `POST /v1/chat/completions`-ը՝ `"model": "9router/auto/..."`-ով, վերադարձնում է 200 (ծայրից ծայր երթուղավորում 9Router-ի միջոցով) - [ ] `GET /dashboard/providers/services/9router/embed/dashboard`-ը ցուցադրում է 9Router-ի բնիկ UI-ը proxy-ի ներսում (առանց ուղիղ `127.0.0.1:port` iframe-ի) - [ ] `POST /api/services/9router/rotate-key`-ը վերադարձնում է `{ keyRotated: true }`, և ծառայությունը մաքուր կերպով վերագործարկվում է - [ ] `POST /api/services/9router/stop`-ը վերադարձնում է 200 և `state: "stopped"` - [ ] `GET /api/services/9router/logs?tail=50`-ը վերադարձնում է SSE հոսք՝ վերջին տողերը պարունակող `snapshot` իրադարձությամբ - [ ] Առանց PATH-ում `npm`-ի միջավայրում տեղադրումը վերադարձնում է 500՝ հասկանալի (առանց stack trace-ի) սխալի հաղորդագրությամբ ### CLIProxyAPI - [ ] `POST /api/services/cliproxy/install`-ը 2 րոպեից պակաս ժամանակում վերադարձնում է 200 - [ ] `POST /api/services/cliproxy/start`-ը 30 վրկ․-ից պակաս ժամանակում վերադարձնում է 200 և `state: "running"` - [ ] `GET /api/services/cliproxy/status`-ը հաղորդում է `health: "healthy"` - [ ] `POST /api/services/cliproxy/stop`-ը վերադարձնում է 200 և `state: "stopped"` - [ ] `GET /api/services/cliproxy/logs?tail=50`-ը վերադարձնում է SSE հոսք ### Անվտանգության ռեգրեսիա - [ ] `curl -H "X-Forwarded-For: 1.2.3.4" http://localhost:20128/api/services/9router/start`-ը վերադարձնում է `403 LOCAL_ONLY` - [ ] `curl -H "X-Forwarded-For: 1.2.3.4" http://localhost:20128/api/services/cliproxy/start`-ը վերադարձնում է `403 LOCAL_ONLY` - [ ] `/api/services/*`-ից ստացվող սխալի պատասխանները չեն պարունակում `err.stack` կամ բացարձակ ֆայլային ուղիներ ## v3.8.0+-ի ստուգումներ Որևէ v3.8.x թողարկում հրապարակելուց առաջ ստուգեք նաև հետևյալ կետերը՝ - [ ] `omniroute --tray`-ը մեկնարկում է macOS-ում (systray2-ը տեղադրված է `~/.omniroute/runtime/`-ում) - [ ] `omniroute --tray`-ը մեկնարկում է Linux-ում (պահանջում է DISPLAY, իսկ չսահմանված լինելու դեպքում տալիս է պատշաճ սխալ) - [ ] `omniroute --tray`-ը մեկնարկում է Windows-ում (PowerShell NotifyIcon, առանց լրացուցիչ երկուական ֆայլերի) - [ ] `omniroute config tray enable`-ը ստեղծում է ավտոմեկնարկի գրառում, իսկ անջատումը հեռացնում է այն - [ ] `npm install -g omniroute@`-ը postinstall-ը գործարկում է առանց ճակատագրական ելքի - [ ] Թարմացման ուղին պահպանում է ընտրովի կախվածությունները. `omniroute update --apply`-ը և ավտոմատ թարմացնողը գործարկում են `npm install -g … --include=optional`, որպեսզի `optionalDependencies`-ը (better-sqlite3, keytar, tls-client և llmlingua SLM փաթեթակազմը՝ `@atjsh/llmlingua-2@2.0.5`, `js-tiktoken`) պահպանվեն թարմացումից հետո։ Ultra `modelPath` SLM մակարդակին անհրաժեշտ է նաև tinybert մոդելը, որն առաջին օգտագործման ժամանակ ավտոմատ ներբեռնվում է `${DATA_DIR}/models/llmlingua`։ Postinstall-ը (`scripts/build/colocateOptionals.mjs`) այնուհետև SLM-ի ընտրովի կախվածությունների ամբողջ շղթան համատեղ տեղակայում է `dist/node_modules`-ում, որպեսզի worker-ը լուծի `@huggingface/transformers` ^4.2.0-ի ՄԵԿ օրինակ. standalone trace-ը փաթեթավորում է միայն transformers-ը, ոչ թե դինամիկ ներմուծվող ընտրովի կախվածությունները, ուստի առանց սրա worker-ը llmlingua-2-ը կբեռներ root-ի transformers-ի հետ, և SLM մակարդակն աննկատ կանցներ fail-open ռեժիմի։ - [ ] `omniroute status`-ն աշխատում է առանց `.env`-ի (CLI նշանի ուղի, միայն loopback) - [ ] `curl http://localhost:20128/api/shutdown`-ը վերադարձնում է 401 (միշտ պաշտպանված երթուղի) - [ ] `curl -H "host: evil.com" http://localhost:20128/api/mcp/sse`-ը վերադարձնում է 401 (loopback պաշտպանիչ ստուգում) - [ ] SQLite runtime-ն առաջին գործարկման ժամանակ լուծվում է որպես `bundled` (փաթեթավորված երկուական ֆայլը վավեր է տվյալ հարթակի համար) - [ ] SQLite runtime-ը հետադարձ անցում է կատարում `runtime`-ի, երբ `node_modules/better-sqlite3`-ը ջնջված է - [ ] Խելացի MCP զտիչը սեղմում է իրական `playwright-mcp browser_snapshot` ելքը (≥50% կրճատում) - [ ] Բոլոր 10 `skills/omniroute*/SKILL.md` ֆայլերը հասանելի են հանրային ներբեռնման համար GitHub-ի raw URL-ի միջոցով - [ ] Առաջնային կարգավորման օգնականը մաքուր տեղակայման դեպքում ցուցադրում է «Ինչպես է այն աշխատում» մակարդակների շրջայցի քայլը - [ ] Գլխավոր վահանակի մակարդակների ծածկույթի widget-ը ցուցադրում է կազմաձևված/ակտիվ քանակները --- ## Հետադարձում Եթե թողարկումն ունի կրիտիկական խնդիր՝ 1. `gh release edit vX.Y.Z --prerelease` (նշում է որպես ոչ վերջին) 2. `git tag -d vX.Y.Z && git push --delete origin vX.Y.Z` (միայն եթե օգտատերերը դեռ չեն սկսել օգտագործել այն) 3. Կամ՝ թեժ ուղղում `release/vX.Y.0`-ում → ուղղիչ թողարկում `vX.Y.(Z+1)` 4. Անմիջապես հաղորդել GitHub Discussions-ում և Discord-ում ## Խիստ կանոններ - Երբեք փոփոխություններ մի ամրագրեք անմիջապես `main`-ում - Երբեք մի օգտագործեք `git push --force`՝ `main` կամ `release/*` ճյուղերի համար - Երբեք մի շրջանցեք Husky-ի կեռիկները (`--no-verify`) - Երբեք մի ամրագրեք գաղտնիքներ, հավատարմագրեր կամ `.env` ֆայլեր - Ծածկույթը պետք է մնա ≥60/60/60/60 (հրահանգներ/տողեր/ֆունկցիաներ/ճյուղավորումներ) - `src/`, `open-sse/`, `electron/` կամ `bin/` պանակներում արտադրական կոդը փոխելիս միշտ ներառեք կամ թարմացրեք թեստերը ## Համաժամացման ավտոմատացված ստուգում Նախքան PR բացելը տեղային միջավայրում գործարկեք փաստաթղթերի համաժամացման պաշտպանիչ ստուգումը՝ ```bash npm run check:docs-sync ``` CI-ն նույնպես գործարկում է այս ստուգումը `.github/workflows/ci.yml`-ում (lint առաջադրանք)։