# 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-ի կողմից սպասարկվող) 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)՝** կարգավորեք Trusted Publisher-ը `omniroute`-ի համար միայն փուլավորման ռեժիմով, որպեսզի արտահոսած երկարաժամկետ նշագիրը չկարողանա որևէ տեղից ուղղակիորեն կատարել `npm publish`․ CI-ն կարող է միայն փուլավորել, իսկ հրապարակել կարող է միայն սեփականատիրոջ 2FA-ն։ **Խափանված արտեֆակտի գործելակարգ (անփոփոխ)՝** `npm deprecate omniroute@ " — use "` որպես կանխադրված արձագանք (րոպեներ է տևում, շրջելի է)․ `npm unpublish`՝ միայն 72h/կախյալներ-չկան պատուհանի ընթացքում և երբեք՝ որպես առաջին քայլ։ 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. **Խստություն**. production-ը խափանված է՝ հրապարակված արտեֆակտը մեկնարկի ժամանակ խափանվում է / անվտանգության շտկում է / թողարկման յուրաքանչյուր օգտատեր տուժում է։ «Կարևոր»-ը չի նշանակում «խափանված»։ 2. **Լիազորություն**. միայն պահոցի սեփականատերն է կիրառում `hotfix` պիտակը։ Պիտակն ԻՆՔՆԻՆ հաստատումն է՝ երբեք ինքնուրույն մի կիրառեք campaign PR-ի վրա։ 3. **Ապացույց**. PR-ի նկարագրությունը հղում է տալիս նախորդ՝ ամբողջությամբ կանաչ ծանր գործարկմանը (այն հավաքակազմին, որը շրջանցված առաջադրանքները կրկին կվավերացնեին), ինչպես նաև տվյալ շտկման՝ սկզբում ձախողվող, ապա հաջող անցնող թեստին։ 4. **Ծավալ**. միայն cherry-pick-ի համար՝ նվազագույն շտկում, առանց վերակառուցումների և կողմնակի փոփոխությունների։ Շրջանցված coverage/ratchet մակերեսը կրկին վավերացվում է release ճյուղի հաջորդ ամբողջական գործարկմամբ (թողարկման շարունակական կանաչ վիճակ)՝ այս ուղին շրջանցում է ՍՊԱՍՈՒՄԸ, ոչ երբեք վավերացումը։ Միայն թեստեր պարունակող տարբերությունները (բոլոր ֆայլերը՝ `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-ի բազային պատկերը արդիական է (ներկայում՝ `node:24.15.0-trixie-slim`) ### Տարբերակ և փոփոխությունների մատյան - [ ] Գործարկել `/version-bump-cc ` (Claude Code հմտություն) - Թարմացնում է տարբերակները `package.json`, `electron/package.json` ֆայլերում - Վերաստեղծում է `CHANGELOG.md`-ը՝ վերջին պիտակից հետո կատարված git commit-ներից - Թարմացնում է README.md-ի տարբերանշանները - [ ] Ձեռքով վերանայել 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:ratchet` — սառեցված `metrics.cycles` վերին սահմանի շրջանակում (`check:cycles`-ն առանց լրացուցիչ պարամետրերի ավարտվում է 1 կոդով ցանկացած ցիկլի դեպքում, #15281) - [ ] `npm run check:any-budget:t11` — բյուջեի շրջանակում - [ ] `npm run check:route-validation:t06` — առանց խնդիրների - [ ] `npm run check:node-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 սերվեր, autoCombo, քեշ) - [ ] `npm run test:coverage` — 60/60/60/60 շեմը բավարարված է (արտահայտություններ/տողեր/ֆունկցիաներ/ճյուղեր) - [ ] `npm run test:integration` — հաջող (եթե փոփոխությունները վերաբերում են DB-ին / մշակիչներին) - [ ] `npm run test:combo:matrix` — հաջող (combo ռազմավարությունների մատրից. դետերմինացված կերպով ապացուցում է բոլոր 19 հանրային երթուղավորման ռազմավարությունների ընտրության որոշումները. գործարկել combo երթուղավորման, ռազմավարության որոշման կամ պահուստային տրամաբանության փոփոխությունների դեպքում) - [ ] `RUN_COMBO_LIVE=1 npm run test:combo:live` — **ըստ ցանկության/ձեռքով** (իրական վերին հոսքի ծխային թեստ՝ պայմանով ակտիվացվող. VPS-ի `root@192.168.0.15` հասցեից վերցնում է միայն ընթերցման համար նախատեսված DB պատկերապատճեն, դիմում է իրական մատակարարներին, ծախսում է կրեդիտներ, երբեք չի գործարկվում CI-ում և առանց ակտիվացման պայմանի մաքուր կերպով բաց է թողնվում) - [ ] `npm run test:combo:live:vps` — **ըստ ցանկության/ձեռքով** (Phase-3 VPS-ի իրական միջավայրի ծխային թեստ. 7 HTTP սցենար իրական `.15` սերվերի նկատմամբ՝ սովորական 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` առաջադրանքով)։ - Թողարկման ճյուղերը push անելուց առաջ ձեռքով գործարկել `npm run test:unit`։ Եթե hook-ը ձախողվում է՝ շտկել հիմքում ընկած խնդիրը և չշրջանցել այն `--no-verify`-ով։ ### Conventional Commits Թողարկման մեջ ներառվող բոլոր commit-ները պետք է հետևեն `type(scope): subject` ձևաչափին։ **Վավեր տիպեր՝** `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`-ը հայտնում է 0 բացակայող բանալի բոլոր 66 նպատակային տեղայնացումներում (`en` սկզբնաղբյուրից բացի յուրաքանչյուր տեղայնացում) - [ ] Եթե անգլերեն սկզբնաղբյուր փաստաթղթերը փոխվել են, պիտակավորումից առաջ գործարկել `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 (պատճենում է standalone + static + public + natives → 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`-ը գոյություն ունի - [ ] Ընտրովի տեղային փաթեթավորված կատարման միջավայրի ծխային թեստ. `npm run dev:candidate -- build`-ից հետո `npm run dev:candidate -- validate`-ը մեկուսացված `DATA_DIR`-ում գործարկում է փաթեթավորված tarball-ը և ստուգում `/api/health` + `/v1/models` (տե՛ս [Ներդրման հիմնական ուղին](CONTRIBUTION_GOLDEN_PATH.md#local-candidate-loop)) ### Թեգավորում և թողարկում - [ ] Գործարկեք `/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`-ն իրական է (հիմնական checkout-ում կամ `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-ն կանաչ է - [ ] Տեղակայեք և ծխային թեստ անցկացրեք OSS Radar երթուղիների համար՝ `RADAR_ENABLED`-ը լռելյայն անջատված պահելով - [ ] Անվանված Radar հոսթում ծխային թեստ անցկացրեք `GET /planos`, `/termos`, `/privacidade` և `/reembolso` ուղիների համար - [ ] Մասնավոր ծառայությունում գրանցեք օպերատորի ինքնությունը/կոնտակտային տվյալները/հասցեն և սեփականատիրոջ կողմից հաստատված իրավական վերանայումը - [ ] Stripe Checkout-ը և ստորագրված webhook-ը փորձարկեք միայն թեստային ռեժիմում - [ ] Փորձարկեք մեկ գաղտնագրված գործարքային էլփոստի առաքում՝ հաստատված ուղարկողով/տիրույթով - [ ] Ապացուցեք պահուստային պատճենից վերականգնումը և վերահսկվող, բյուջեով սահմանափակված մեկ հետազոտական գործարկումը - [ ] Նախքան նվիրատվության ապացույց ընդունելը հաստատեք BRL/PIX վերանայման քաղաքականությունը - [ ] Հանրային Checkout-ը միացրեք միայն նախորդ անցակետերն անցնելուց հետո, ապա ակտիվացրեք `news.json`-ի նոր ID-ն - [ ] Ստուգեք, որ Home բաններն օգտագործում է տեղայնացված տեքստ, և նոր ID-ն կրկին ցուցադրվում է ավելի հին ID-ն մերժելուց հետո ## Ներկառուցված ծառայությունների արագ ստուգում (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` վերադարձնում է 200՝ `installedVersion`-ով, 2 րոպեից պակաս ժամանակում - [ ] `POST /api/services/9router/start` վերադարձնում է 200 և `state: "running"`՝ 30 վրկ-ից պակաս ժամանակում - [ ] `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-ը պրոքսիի ներսում (առանց անմիջական `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` վերադարձնում է 200՝ 2 րոպեից պակաս ժամանակում - [ ] `POST /api/services/cliproxy/start` վերադարձնում է 200 և `state: "running"`՝ 30 վրկ-ից պակաս ժամանակում - [ ] `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-ի ՄԵԿ օրինակ․ ինքնուրույն trace-ը փաթեթավորում է միայն transformers-ը, ոչ թե դինամիկ ներմուծվող ընտրովի կախվածությունները, ուստի առանց սրա worker-ը կբեռներ llmlingua-2-ը root-ի transformers-ի հետ, և SLM մակարդակն աննկատ կանցներ fail-open ռեժիմի։ - [ ] `omniroute status`-ը աշխատում է առանց `.env`-ի (CLI token-ի ուղի, միայն loopback) - [ ] `curl http://localhost:20128/api/shutdown` վերադարձնում է 401 (միշտ պաշտպանված երթուղի) - [ ] `curl -H "host: evil.com" http://localhost:20128/api/mcp/sse` վերադարձնում է 401 (loopback-ի պաշտպանություն) - [ ] Առաջին գործարկման ժամանակ SQLite runtime-ը որոշվում է որպես `bundled` (ներկառուցված երկուական ֆայլը վավեր է հարթակի համար) - [ ] `node_modules/better-sqlite3`-ը ջնջելու դեպքում SQLite runtime-ը հետադարձաբար անցնում է `runtime`-ի - [ ] Խելացի MCP զտիչը սեղմում է իրական `playwright-mcp browser_snapshot` ելքը (≥50% կրճատում) - [ ] Բոլոր 10 `skills/omniroute*/SKILL.md` ֆայլերը հրապարակայնորեն հասանելի են GitHub-ի raw URL-ով - [ ] Առաջնային կարգավորման հրաշագործը թարմ տեղակայման ժամանակ ցուցադրում է «Ինչպես է այն աշխատում» մակարդակների շրջայցի քայլը - [ ] Գլխավոր վահանակի մակարդակների ծածկույթի վիջեթը ցուցադրում է կազմաձևված/ակտիվ քանակները --- ## 3.9.0 LTS ճյուղավորումը (փորձարկվել է 3.8.58-ում) v3.8.59-ից հետո հաջորդ տարբերակը 3.9.0-ն է, և դրա վերջին commit-ից ստեղծվում են երկու երկարաժամկետ ճյուղեր՝ `stable/v3` (v3 LTS գիծը, npm `latest`) և `develop` (v4, տարբերակը բարձրացված է մինչև 4.0.0, npm `nightly`)։ Ճյուղերի/ալիքների մոդելը, առաջ փոխադրումը և պիտակները նկարագրված են [RELEASE_STRATEGY.md](./RELEASE_STRATEGY.md)-ում, իսկ պլանը՝ [ROADMAP](../../ROADMAP.md)-ում (Փուլ 3)։ Ճյուղավորումն իրականացվում է մեկ անգամ. 3.8.58-ը սկզբից մինչև վերջ փորձարկում է այն fork-ում, իսկ 3.8.59-ն ավարտվում է [GO/NO-GO ստուգաթերթով](./LTS_GO_NO_GO.md)։ ### Փորձնական գործարկում (միայն ընթերցում, անվտանգ է ցանկացած պահի) ```bash npm run release:dry-run-lts-cut # իրական ճյուղավորումը՝ 3.9.0՝ HEAD-ից, նախորդ թեգը՝ v3.8.59 npm run release:dry-run-lts-cut -- --from <3.9.0-tip> # ամրագրել սկզբնաղբյուր commit-ը ``` `scripts/release/dry-run-lts-cut.mjs`-ը ոչինչ չի կատարում. այն կարդում է git-ի և `gh`-ի տվյալները և արտածում ամբողջ հաջորդականությունը՝ նախապայմանները (սկզբնաղբյուրը որոշվում է, սկզբնաղբյուր պահոցն ունի ամբողջական պատմություն. մակերեսային clone-ը չի կարող push անել `stable/v3`, ընդունող կողմը մերժում է փաթեթը առաջին արհեստականորեն միացված ծնող commit-ի մոտ, ուստի նախ կատարեք ճյուղավորումն ամբողջական clone-ից կամ `git fetch --unshallow origin` — նախորդ թեգը գոյություն ունի, `package.json`-ում նշված է նպատակային տարբերակը, բաց է `release-freeze` issue, գոյություն ունեցող թողարկման ճյուղում բաց `Release branch not green` issue չկա. գոյություն չունեցող ճյուղը հաղորդում է անհայտ `?` վիճակ և երբեք կանաչ չի համարվում. Mergify-ի `release` հերթը կազմաձևված է (G11՝ `queue_rules`, `checks_timeout`, `queue` պիտակ), `release/*` կանոնների հավաքածուն դեռ արգելափակում է ջնջումը և force-push-ը, իսկ `stable/v3`-ը և `develop`-ը դեռ գոյություն չունեն), ճյուղերի երկու քայլերը, dormant workflow-ների որ trigger-ներն ու `if:` պայմաններն են դառնում true (և որոնք են մնում պահոցի փոփոխականով սահմանափակված կամ կանոնական պահոցին ամրագրված), սպասվող dist-tag-երը (`latest` → 3.9.0, `next` և `nightly`՝ դատարկ) և հետադարձումը։ Ելքի `0` = `RESULT: READY`, `1` = արգելափակող նախապայմանը չի կատարվել (`✗`), `2` = օգտագործման սխալ։ `--advisory `-ը ստուգումը դարձնում է նախազգուշացում (`!`)՝ առանց այն թաքցնելու։ Իրական ճյուղավորման փորձնական գործարկումը կատարեք, քանի դեռ 3.9.0-ի թողարկման սառեցումը բաց է. ճյուղերը ստեղծվում են թեգից հետո և մինչև Փուլ 12c-ում սառեցումը վերացնելը։ ### 3.8.58-ի փորձարկում (միայն fork-ում) ```bash # 1. Փորձնական գործարկում ընթացիկ վերջին commit-ի վրա՝ փորձարկման պարամետրերով npm run release:dry-run-lts-cut -- --target-version 3.8.58 --previous-tag v3.8.57 \ --advisory freeze,base-green # 2. Կատարել FORK remote-ի նկատմամբ (origin-ը կամ ցանկացած remote, որի URL-ը կանոնական # պահոցինն է, մերժվում է. յուրաքանչյուր քայլի համար տերմինալում հաստատում է պահանջվում) git remote add rehearsal https://github.com//OmniRoute.git node scripts/release/dry-run-lts-cut.mjs --execute --remote rehearsal \ --target-version 3.8.58 --previous-tag v3.8.57 --advisory freeze,base-green # 3. Գործարկել dormant workflow-ները fork-ում (workflow_dispatch այնտեղ, որտեղ փորձնական գործարկումը # հայտնում է կանոնական պահոցին ամրագրում), ապա հետադարձել node scripts/release/dry-run-lts-cut.mjs --execute --rollback --remote rehearsal \ --target-version 3.8.58 --previous-tag v3.8.57 --advisory freeze,base-green ``` develop-ի տարբերակը բարձրացնող commit-ը ստեղծվում է git plumbing-ի միջոցով (աշխատանքային ծառը չի փոփոխվում) և թարմացնում է նույն հինգ ֆայլերը, ինչ ցիկլը բացող commit-ը՝ `package.json`, `open-sse/package.json`, `electron/package.json`, `package-lock.json` և `docs/openapi.yaml`։ `[4.0.0]` CHANGELOG բաժինը և դրա i18n պատճենները դրանից հետո բացվում են `develop`-ում՝ մինչև դրա առաջին PR-ը։ Սկրիպտը երբեք չի փոփոխում npm dist-tag-երը. դրանք փորձարկեք ժամանակավոր փաթեթի վրա։ ### PR-ի նախադիտման արտեֆակտ (կառուցել մեկ անգամ, առաջխաղացնել նույն բայթերը) `.github/workflows/preview-artifact.yml`-ը PR-ի head-ից կառուցում է մեկ production tarball և վավերացնում հենց այդ build-ը (#8084 հատված (a))։ Միայն նույն պահոցի PR-ներ. ոչինչ չի հրապարակվում։ ```bash gh workflow run preview-artifact.yml -f pr_number= # կամ ավելացրեք `preview-artifact` պիտակը gh run download --name preview-artifact-pr- --dir preview cd preview && sha256sum -c SHA256SUMS gh attestation verify omniroute-*.tgz --repo diegosouzapw/OmniRoute npm install -g ./omniroute-*.tgz # նախադիտման տեղադրում ``` Գործարկումը կատարում է `npm ci`, `npm run build:release`, `npm run check:pack-artifact`, փաթեթավորում է tarball-ը, գործարկում `npm run check:pack-boot` (կեղծ գաղտնիքներ, ժամանակավոր տվյալների գրացուցակ), կրկին փաթեթավորում է և ձախողվում, եթե digest-ը նույնական չէ, ապա գրանցում է `artifact-identity.json`-ը (head SHA, base SHA, lockfile hash, հարթակ, ճարտարապետություն, node ABI, bundler, կառուցման քաղաքականություն՝ `scripts/release/artifact-identity.mjs`) և առանձին job-ում հաստատում է tarball-ի ծագումը։ Նախադիտման առաջխաղացումը նշանակում է տեղադրել այդ tarball-ը. երբեք մի վերակառուցեք սկզբնաղբյուրից։ ### Ճյուղավորումը (3.9.0, GO-ից հետո) 1. GO-ն գրանցված է [LTS_GO_NO_GO.md](./LTS_GO_NO_GO.md)-ում։ 2. `npm run release:dry-run-lts-cut -- --from v3.9.0`-ն արտածում է `RESULT: READY`։ 3. Ձեռքով ստեղծեք ճյուղերը `origin`-ում՝ փորձնական գործարկման արտածած հրամաններով. սկրիպտը հրաժարվում է push անել դեպի `origin`։ Վերանայված develop commit-ը կրկին օգտագործելու համար նախ կատարեք `--execute` փորձարկումը 3.9.0-ի վերջին commit-ի վրա՝ ձեր fork-ի նկատմամբ. այն արտածում է երկու SHA-ներն էլ, և նույն commit-ները կարելի է push անել. ```bash git push origin :refs/heads/stable/v3 :refs/heads/develop ``` 4. Պաշտպանեք `stable/v3`-ը և `develop`-ը (կանոնների հավաքածուներ + միաձուլման հերթ), նախքան առաջին PR-ի մուտքը։ 5. Չգործարկված աշխատանքային հոսքերն ակտիվանում են ճյուղի առկայությամբ՝ `forward-port.yml` (`stable/v3` ուղարկման դեպքում), `validate-stable-pr.yml` (`stable/v3`-ին ուղղված PR-ների համար) և `nightly-v4-build.yml` (`develop`-ի կառուցումներ)։ Նախքան գործարկումը սահմանեք պահոցի `secrets.FORWARD_PORT_TOKEN` գաղտնիքը (որպեսզի CI-ն աշխատի առաջ տեղափոխման PR-ների համար)։ Գիշերային հրապարակումը կմնա անջատված, մինչև պատասխանատուն պահոցի `vars.NIGHTLY_PUBLISH` փոփոխականի արժեքը սահմանի `true`, իսկ npm Trusted Publishing-ը ընդունի `nightly-v4-build.yml`-ը։ Ալիքի որոշումն իրականացնում է `scripts/release/dist-tag.mjs`-ը՝ նույն որոշիչը, որն օգտագործում է `npm-publish.yml`-ը։ 6. Ստուգեք ալիքները․ `npm view omniroute dist-tags --json`-ը պետք է ցույց տա `latest` = 3.9.0 և չպարունակի `next` / `nightly`, մինչև v4-ի հրապարակումը։ 7. Անհրաժեշտության դեպքում հետ գլորեք փոփոխությունները՝ `git push origin --delete refs/heads/stable/v3 refs/heads/develop` և `npm dist-tag add omniroute@3.8.59 latest`։ --- ## Հետադարձում Եթե թողարկումն ունի լուրջ խնդիր՝ 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 առաջադրանք)։