# 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) · 🇪🇸 [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) · 🇦🇲 [hy](../../../hy/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 της έκδοσης ξεκινά σε πράσινη κατάσταση. ## TL;DR ```bash # 1. Αυξήστε την έκδοση + δημιουργήστε το CHANGELOG (δεξιότητα) /version-bump-cc patch # ή minor/major # 2. Εκτελέστε το ποιοτικό σημείο ελέγχου τοπικά npm run check # lint + δοκιμές npm run test:coverage # πλήρης έλεγχος κάλυψης (60/60/60/60) # 3. Δημιουργήστε το build και εκτελέστε δοκιμή smoke 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 (προεπιλογή από την v3.8.51) — σταδιακή κατόπιν αιτήματος, άμεση ως εναλλακτική λύση Το `npm-publish.yml` δημοσιεύει μέσω της **Αξιόπιστης δημοσίευσης npm (OIDC)** από προεπιλογή: η εργασία `stage-npm` (φιλοξενούμενη από το GitHub) ανταλλάσσει το id-token του GitHub με ένα βραχύβιο διαπιστευτήριο npm για τη συγκεκριμένη εκτέλεση — χωρίς μακρόβιο npm token στα μυστικά του αποθετηρίου, χωρίς προτροπή 2FA, με συνημμένη προέλευση. Αυτή είναι η παράκαμψη που εγκρίνει πλέον το npm, καθώς τα token που παρακάμπτουν το 2FA αποσύρονται· επαναφέρει την πλήρως αυτόματη ροή που είχε το έργο έως την v3.8.48, διατηρώντας παράλληλα την εγγύηση WS1.3 (ένα token που έχει διαρρεύσει δεν μπορεί να δημοσιεύσει μόνο του — δεν υπάρχει token). **Αρχική ρύθμιση μίας φοράς (κάτοχος):** npmjs.com → πακέτο `omniroute` → Settings → _Trusted Publisher_ → GitHub: κάτοχος `diegosouzapw`, αποθετήριο `OmniRoute`, ροή εργασίας `npm-publish.yml` (περιβάλλον: κανένα). Μέχρι να υπάρχει αυτή η ρύθμιση, το αυτόματο βήμα αποτυγχάνει με `ENEEDAUTH`: εκκινήστε το ξανά με `publish_mode=staged` (παρακάτω) ή `direct`. ### Σταδιακή δημοσίευση (κατόπιν αιτήματος — `publish_mode=staged`) Η ροή εργασίας npm-publish δεν δημοσιεύει πλέον απευθείας: εκκινεί το συσκευασμένο tarball (`check:pack-boot`) και κατόπιν εκτελεί `npm stage publish` — τα ακριβή byte σταθμεύουν στο μητρώο, **χωρίς δυνατότητα εγκατάστασης** έως ότου τα εγκρίνει ο κάτοχος. Η ανθρώπινη πύλη 2FA μεταφέρθηκε ΜΕΤΑ την επαλήθευση, όχι πριν από αυτήν. **Ροή κατόχου αφού η ροή εργασίας γίνει πράσινη:** 1. `npm stage list omniroute` — εντοπίστε το αναγνωριστικό του σταδίου (εμφανίζεται επίσης στη σύνοψη της ροής εργασίας). 2. Επαληθεύστε τα σταδιακά αποθηκευμένα byte (συνιστάται): `npm stage download ` και, στη συνέχεια, εγκαταστήστε το ληφθέν tarball σε ένα προσωρινό πρόθεμα και εκκινήστε το (το `npm run check:pack-boot` αυτοματοποιεί την ίδια ετυμηγορία πακετάρισμα→εγκατάσταση→εκκίνηση στο CI). 3. `npm stage approve ` — η προτροπή 2FA ΕΙΝΑΙ η δημοσίευση. Το `npm stage reject ` απορρίπτει το στάδιο. 4. Δίχτυ ασφαλείας μετά τη δημοσίευση: ο επαληθευτής μετά τη δημοσίευση (WS1.4 του σχεδίου v3.8.49) εγκαθιστά τη δημοσιευμένη έκδοση από το δημόσιο μητρώο σε ένα καθαρό κοντέινερ και την εκκινεί. **Εναλλακτική λύση έκτακτης ανάγκης:** το `workflow_dispatch` με `publish_mode=direct` επαναφέρει την παλαιού τύπου άμεση εκτέλεση του `npm publish` (χρησιμοποιήστε το μόνο εάν η ίδια η σταδιακή δημοσίευση δυσλειτουργεί· καταγράψτε τον λόγο). **Ενίσχυση μίας φοράς (κάτοχος, npmjs.com):** διαμορφώστε τον Trusted Publisher για το `omniroute` σε λειτουργία μόνο σταδιακής δημοσίευσης, ώστε ένα μακρόβιο token που έχει διαρρεύσει να μην μπορεί να εκτελέσει `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**. Μετά την εργασία: το digest του `latest` στο Hub ισούται με το digest του νέου SemVer και το `last_updated` έχει ενημερωθεί. Μην αφήνετε το `:latest` σε παλαιότερο build ενώ οι σημειώσεις έκδοσης αναφέρονται σε διορθώσεις που υπάρχουν μόνο στο git. Οι γρήγοροι οδηγοί εκκίνησης του Compose χρησιμοποιούν το `:latest`· το GitOps θα πρέπει να συνεχίσει να καρφιτσώνει το `X.Y.Z`. Δείτε [Κανάλια έκδοσης Docker](../guides/DOCKER_GUIDE.md#release-channels) και #10317. ## Γρήγορη λωρίδα επειγουσών διορθώσεων (ετικέτα `hotfix`) Ένα PR με την ετικέτα `hotfix` παρακάμπτει το βαρύ πλέγμα CI (E2E 9 τμημάτων, μηχανισμό σταδιακής αύξησης κάλυψης, quality-gate, quality-extended) και διατηρεί τους γρήγορους ελέγχους υψηλής αξιοπιστίας: build, τμήματα unit tests, integration, vitest, lint/typecheck, docs-sync, `check:pack-artifact` και τον έλεγχο εκκίνησης του tarball (`check:pack-boot`). Στόχος: επιτυχής ολοκλήρωση σε ≤15min αντί για ~33min. **Πολιτική εισόδου — απαιτούνται και τα τέσσερα (κατά τα πρότυπα των λωρίδων έκτακτης ανάγκης των Chromium/VS Code/Node):** 1. **Σοβαρότητα**: το περιβάλλον παραγωγής δεν λειτουργεί — ένα δημοσιευμένο artifact καταρρέει κατά την εκκίνηση / πρόκειται για διόρθωση ασφαλείας / επηρεάζεται κάθε χρήστης της έκδοσης. Το «σημαντικό» δεν σημαίνει «μη λειτουργικό». 2. **Εξουσιοδότηση**: μόνο ο ιδιοκτήτης του repository εφαρμόζει την ετικέτα `hotfix`. Η ετικέτα ΑΠΟΤΕΛΕΙ την έγκριση — δεν εφαρμόζεται ποτέ με αυτοεξυπηρέτηση σε PR μιας καμπάνιας. 3. **Αποδεικτικά στοιχεία**: το σώμα του PR περιλαμβάνει σύνδεσμο προς την προηγούμενη πλήρως επιτυχημένη εκτέλεση του βαρέος συνόλου ελέγχων (το σύνολο που θα επαλήθευαν εκ νέου οι εργασίες που παραλείφθηκαν), καθώς και το test της ίδιας της διόρθωσης που πρώτα αποτυγχάνει και έπειτα επιτυγχάνει. 4. **Εύρος**: μόνο cherry-pick — η ελάχιστη δυνατή διόρθωση, χωρίς refactors και χωρίς άσχετες συνοδευτικές αλλαγές. Η επιφάνεια coverage/ratchet που παραλείφθηκε επαληθεύεται εκ νέου από την επόμενη πλήρη εκτέλεση στο release branch (συνεχώς επιτυχής κατάσταση έκδοσης) — η λωρίδα παρακάμπτει την ΑΝΑΜΟΝΗ, ποτέ την επικύρωση. Οι αλλαγές που αφορούν μόνο tests (όλα τα αρχεία κάτω από το `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 μετά την τελευταία ετικέτα - Ενημερώνει τα διακριτικά του README.md - [ ] Ελέγξτε χειροκίνητα το CHANGELOG.md και διορθώστε τα μηνύματα δεσμεύσεων, εάν χρειάζεται - [ ] Βεβαιωθείτε ότι η πιο πρόσφατη ενότητα semver στο `CHANGELOG.md` αντιστοιχεί στην έκδοση του `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`, σύμφωνα με το `SUPPORTED_NODE_RANGE` στο `src/shared/utils/nodeRuntimeSupport.ts`· ευθυγραμμισμένο με το `engines` του `package.json`) ### Δοκιμές - [ ] `npm run test:unit` — επιτυχία - [ ] `npm run test:vitest` — επιτυχία (διακομιστής MCP, autoCombo, προσωρινή μνήμη) - [ ] `npm run test:coverage` — ικανοποιείται το όριο 60/60/60/60 (εντολές/γραμμές/συναρτήσεις/κλάδοι) - [ ] `npm run test:integration` — επιτυχία (εάν οι αλλαγές επηρεάζουν τη ΒΔ / τους χειριστές) - [ ] `npm run test:combo:matrix` — επιτυχία (πίνακας στρατηγικών combo: αποδεικνύει ντετερμινιστικά τις αποφάσεις επιλογής και των 19 δημόσιων στρατηγικών δρομολόγησης· εκτελέστε το όταν αλλάζετε τη δρομολόγηση combo, την επίλυση στρατηγικής ή τη λογική εφεδρείας) - [ ] `RUN_COMBO_LIVE=1 npm run test:combo:live` — **προαιρετικό/χειροκίνητο** (δοκιμή smoke με ελεγχόμενη πρόσβαση σε πραγματικό upstream· αντλεί ένα στιγμιότυπο ΒΔ μόνο για ανάγνωση από το VPS `root@192.168.0.15`· χρησιμοποιεί πραγματικούς παρόχους και καταναλώνει πιστώσεις· δεν εκτελείται ποτέ στο CI· παραλείπεται ομαλά χωρίς την ενεργοποίηση) - [ ] `npm run test:combo:live:vps` — **προαιρετικό/χειροκίνητο** (ζωντανή δοκιμή smoke VPS της Phase-3: 7 σενάρια HTTP έναντι του ζωντανού διακομιστή `.15` μέσω απλού Node ESM· απαιτεί `ssh root@192.168.0.15`· δημιουργεί/διαγράφει μόνο combo `__live_test__*`· χρησιμοποιεί πραγματικούς παρόχους· δεν εκτελείται ποτέ στο CI) - [ ] `npm run test:e2e` — επιτυχία (αλλαγές UI) - [ ] `npm run test:protocols:e2e` — επιτυχία (αλλαγές MCP/A2A) - [ ] `npm run test:ecosystem` — επιτυχία ### Hooks (επικυρωμένα από το Husky) Τα hooks του Husky βρίσκονται στο `.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`). - Εκτελέστε χειροκίνητα το `npm run test:unit` πριν προωθήσετε κλάδους έκδοσης. Εάν αποτύχει κάποιο hook: διορθώστε το υποκείμενο πρόβλημα, μην το παρακάμψετε με `--no-verify`. ### Συμβατικές δεσμεύσεις Όλες οι δεσμεύσεις που προορίζονται για την έκδοση πρέπει να ακολουθούν τη μορφή `type(scope): subject`. **Έγκυροι τύποι:** `feat`, `fix`, `refactor`, `docs`, `test`, `chore`, `perf`, `style`, `ci` **Έγκυρα πεδία:** `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:` ή το `!` μετά το πεδίο (π.χ. `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`) είναι συγχρονισμένη με τα πηγαία έγγραφα (δεν υπάρχουν αποκλίσεις πηγών στην αυστηρή λειτουργία· η συμβουλευτική προειδοποίηση στη λειτουργία warn είναι αποδεκτή για διορθώσεις τεκμηρίωσης της τελευταίας στιγμής, αλλά ο κωδικός πρέπει να είναι 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` - [ ] Δοκιμή σε υπάρχουσα εγκατάσταση: δημιουργήστε αντίγραφο ασφαλείας της ΒΔ, εκτελέστε τη μετεγκατάσταση και επαληθεύστε το σχήμα - [ ] Τα αρχεία WAL (`-wal`, `-shm`) αντιμετωπίζονται σωστά εάν η μετεγκατάσταση επανεγγράφει πίνακες ### Κατάλογος παρόχων (επικυρωμένος με Zod) - [ ] Το σχήμα Zod στο `src/shared/constants/providers.ts` είναι έγκυρο κατά τη φόρτωση - [ ] Όλοι οι πάροχοι διαθέτουν τα απαιτούμενα πεδία (`id`, `label`, `kind` κ.λπ.) - [ ] Παρέχεται `freeNote` για τους νέους δωρεάν παρόχους - [ ] Οι πάροχοι OAuth έχουν καταχωρισμένο `oauthConfig` στο `src/lib/oauth/constants/oauth.ts` - [ ] Αν προστέθηκε νέος πάροχος: υπάρχει αντίστοιχος executor στο `open-sse/executors/` - [ ] Αν η μορφή δεν είναι OpenAI: υπάρχει translator στο `open-sse/translator/` - [ ] Τα μοντέλα είναι καταχωρισμένα στο `open-sse/config/providerRegistry.ts` - [ ] Οι μοναδιαίες δοκιμές στο `tests/unit/` καλύπτουν την ταξινόμηση και τη δρομολόγηση παρόχων ### Εφαρμογή υπολογιστή (Electron) Αν άλλαξε το `electron/`: - [ ] Το `npm run electron:smoke:packaged` ολοκληρώνεται επιτυχώς - [ ] Οι εκδόσεις build έχουν δοκιμαστεί για τουλάχιστον ένα από τα `:win`, `:mac`, `:linux` - [ ] Τα πιστοποιητικά υπογραφής κώδικα δεν έχουν λήξει (αν γίνεται υπογραφή) - [ ] Η έκδοση στο `electron/package.json` αντιστοιχεί σε εκείνη του ριζικού `package.json` - [ ] Ο δείκτης του καναλιού αυτόματης ενημέρωσης έχει ενημερωθεί, αν γίνεται έκδοση στο `stable` ### Διάταξη build Το αποθετήριο χρησιμοποιεί τρεις διακριτούς καταλόγους εξόδου — μην τους συγχέετε ποτέ: | Κατάλογος | Σκοπός | Παρακολουθείται; | | --------- | ------------------------------------------------------------------ | ------------------- | | `src/` | Πηγαίος κώδικας εφαρμογής (TypeScript / TSX) | Ναι | | `.build/` | Ενδιάμεσα αρχεία build — έξοδος `next build` (`distDir`) | Όχι (στο gitignore) | | `dist/` | Διανεμήσιμο npm bundle — δημιουργείται από το `assembleStandalone` | Όχι (στο gitignore) | > **Σημείωση για τον χειριστή:** ο κατάλογος εικόνας στο απομακρυσμένο VPS παραμένει `/usr/lib/node_modules/omniroute/app/`. > Μόνο η έξοδος build **εντός του αποθετηρίου** μετακινήθηκε (`app/` → `dist/`). Οι δεξιότητες deploy συγχρονίζουν μέσω rsync > τα περιεχόμενα του `dist/` στον απομακρυσμένο κατάλογο `app/` — δεν απαιτούνται αλλαγές στις διαδρομές του VPS. **Ροή ενιαίου build:** ``` 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` για deploy — χρησιμοποιήστε το `npm run build:release`, το οποίο εκτελεί καθαρό rebuild και δημιουργεί τον δείκτη με μία εντολή. ### Επικύρωση τεχνουργημάτων - [ ] Το `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` υπάρχει μετά το build - [ ] Προαιρετική τοπική δοκιμή smoke του πακεταρισμένου runtime: το `npm run dev:candidate -- validate`, μετά το `npm run dev:candidate -- build`, εκκινεί το πακεταρισμένο tarball σε απομονωμένο `DATA_DIR` και ελέγχει τα `/api/health` + `/v1/models` (δείτε τη [Χρυσή διαδρομή συνεισφοράς](CONTRIBUTION_GOLDEN_PATH.md#local-candidate-loop)) ### Προσθήκη tag και έκδοση - [ ] Εκτελέστε `/generate-release-cc` (δεξιότητα Claude Code): - Δημιουργεί το tag `vX.Y.Z` - Ωθεί το tag και το branch - Ανοίγει GitHub Release με το σώμα του changelog - Επισυνάπτει τα προγράμματα εγκατάστασης 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 ``` ### Deploy Οι δεξιότητες deploy χρησιμοποιούν την ελαφριά ροή rsync — χωρίς `npm pack`, χωρίς `npm i -g`: - [ ] Χρησιμοποιήστε τη δεξιότητα deploy που αντιστοιχεί στον στόχο: - `/deploy-vps-local-cc` — τοπικό VPS (192.168.0.15) - `/deploy-vps-akamai-cc` — Akamai VPS (69.164.221.35) - `/deploy-vps-both-cc` — και τα δύο - [ ] Πριν από το deploy, επιβεβαιώστε ότι `dist/BUILD_SHA` == `git rev-parse --short HEAD` - [ ] Το build πρέπει να εκτελείται εκεί όπου το `node_modules` είναι πραγματικό (κύριο checkout ή worktree όπου έχει εκτελεστεί `npm ci` — ΟΧΙ worktree με συμβολικό σύνδεσμο) - [ ] Εκτελέστε δοκιμή smoke στο αναπτυγμένο στιγμιότυπο: - Ανοίξτε το `/dashboard/health` → ελέγξτε ότι η συμβολοσειρά έκδοσης αντιστοιχεί στην έκδοση - Εκτελέστε ένα αίτημα `/v1/chat/completions` προς έναν γνωστό πάροχο - Επαληθεύστε ότι το `/api/monitoring/health` επιστρέφει circuit breakers σε κατάσταση `CLOSED` - Επιβεβαιώστε ότι τα transport του MCP αποκρίνονται (`/mcp` HTTP, `/mcp-sse` SSE) ### Μετά την έκδοση - [ ] Εκτελέστε `/capture-release-evidences-cc` (δεξιότητα Claude Code) - Καταγράφει στιγμιότυπα οθόνης/εγγραφές WebP των νέων λειτουργιών - Τα επισυνάπτει στις σημειώσεις έκδοσης / στην ανάρτηση ιστολογίου - [ ] Ενημερώστε τα GitHub Discussions / το Discord με ανακοίνωση της έκδοσης - [ ] Ανοίξτε milestone για την επόμενη έκδοση - [ ] Αν είναι κρίσιμο: καρφιτσώστε τη συζήτηση ή δημοσιεύστε στο `news.json` για banner εντός της εφαρμογής ### Πύλη δημόσιας κυκλοφορίας του Radar Η ανακοίνωση του Radar έχει σκόπιμα γίνει commit με `active: false`. Η ενεργοποίηση αποτελεί ξεχωριστή αλλαγή αφού τεκμηριωθεί κάθε παρακάτω στοιχείο: - [ ] Όλα τα διαδοχικά Radar PR έχουν συγχωνευθεί και το CI του release-tip είναι επιτυχές - [ ] Κάντε deploy και δοκιμή smoke στις διαδρομές OSS του Radar, με το `RADAR_ENABLED` να παραμένει απενεργοποιημένο από προεπιλογή - [ ] Κάντε δοκιμή smoke στα `GET /planos`, `/termos`, `/privacidade` και `/reembolso` στον καθορισμένο host του Radar - [ ] Καταγράψτε την ταυτότητα/τα στοιχεία επικοινωνίας/τη διεύθυνση του χειριστή και τη νομική αξιολόγηση που έχει εγκριθεί από τον ιδιοκτήτη στην ιδιωτική υπηρεσία - [ ] Δοκιμάστε το Stripe Checkout και το υπογεγραμμένο webhook μόνο σε λειτουργία δοκιμής - [ ] Δοκιμάστε μία κρυπτογραφημένη παράδοση email συναλλαγής με τον εγκεκριμένο αποστολέα/τομέα - [ ] Αποδείξτε την επαναφορά αντιγράφου ασφαλείας και μία επιβλεπόμενη εκτέλεση έρευνας με ανώτατο όριο προϋπολογισμού - [ ] Εγκρίνετε την πολιτική ελέγχου BRL/PIX πριν από την αποδοχή αποδεικτικών δωρεάς - [ ] Ενεργοποιήστε το δημόσιο Checkout μόνο μετά τις προηγούμενες πύλες και, στη συνέχεια, ενεργοποιήστε το νέο ID του `news.json` - [ ] Επαληθεύστε ότι το banner της αρχικής σελίδας χρησιμοποιεί τοπικοποιημένο κείμενο και ότι ένα νέο ID επανεμφανίζεται μετά την απόρριψη ενός παλαιότερου ID ## Δοκιμή smoke ενσωματωμένων υπηρεσιών (v3.8.4+) Πριν από τη διάθεση οποιασδήποτε έκδοσης που περιλαμβάνει αλλαγές στις ενσωματωμένες υπηρεσίες, επαληθεύστε τα εξής: ### Εκκίνηση με νέα βάση δεδομένων (εντοπίζει συγκρούσεις migrations — προστέθηκε μετά το hotfix της v3.8.4) - [ ] `DATA_DIR=$(mktemp -d) npm start &` — περιμένετε 10 s για την εκκίνηση - [ ] Το `curl -s http://127.0.0.1:20128/api/services/9router/status | jq '.tool'` επιστρέφει `"9router"` (ΟΧΙ 404, ΟΧΙ 500). Επιβεβαιώνει ότι εφαρμόστηκε το migration `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 min - [ ] Το `POST /api/services/9router/start` επιστρέφει 200 και `state: "running"` σε λιγότερο από 30 s - [ ] Το `GET /api/services/9router/status` αναφέρει `health: "healthy"` - [ ] Το `POST /v1/chat/completions` με `"model": "9router/auto/..."` επιστρέφει 200 (δρομολόγηση από άκρο σε άκρο μέσω του 9Router) - [ ] Το `GET /dashboard/providers/services/9router/embed/dashboard` αποδίδει το εγγενές UI του 9Router μέσα στον proxy (χωρίς άμεσο iframe προς `127.0.0.1:port`) - [ ] Το `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` που περιέχει πρόσφατες γραμμές - [ ] Η εγκατάσταση σε περιβάλλον χωρίς `npm` στο PATH επιστρέφει 500 με ένα φιλικό μήνυμα σφάλματος (χωρίς stack trace) ### CLIProxyAPI - [ ] Το `POST /api/services/cliproxy/install` επιστρέφει 200 σε λιγότερο από 2 min - [ ] Το `POST /api/services/cliproxy/start` επιστρέφει 200 και `state: "running"` σε λιγότερο από 30 s - [ ] Το `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 χωρίς μοιραίο τερματισμό - [ ] Η διαδρομή ενημέρωσης διατηρεί τα προαιρετικά dependencies: το `omniroute update --apply` και το πρόγραμμα αυτόματης ενημέρωσης εκτελούν `npm install -g … --include=optional`, ώστε τα `optionalDependencies` (better-sqlite3, keytar, tls-client και η στοίβα SLM του llmlingua: `@atjsh/llmlingua-2@2.0.5`, `js-tiktoken`) να διατηρούνται μετά από μια ενημέρωση. Το επίπεδο SLM ultra `modelPath` χρειάζεται επίσης το μοντέλο tinybert, το οποίο λαμβάνεται αυτόματα στο `${DATA_DIR}/models/llmlingua` κατά την πρώτη χρήση. Στη συνέχεια, το postinstall (`scripts/build/colocateOptionals.mjs`) τοποθετεί μαζί το προαιρετικό closure του SLM στο `dist/node_modules`, ώστε ο worker να επιλύει ΜΙΑ ΜΟΝΟ παρουσία του `@huggingface/transformers` ^4.2.0 — το αυτόνομο trace συμπεριλαμβάνει μόνο το transformers, όχι τα optionals που εισάγονται δυναμικά, επομένως, χωρίς αυτό, ο worker θα φόρτωνε το llmlingua-2 με το transformers του root και το επίπεδο SLM θα αποτύγχανε σιωπηρά σε λειτουργία fail-open. - [ ] Το `omniroute status` λειτουργεί χωρίς `.env` (διαδρομή token του CLI, μόνο loopback) - [ ] Το `curl http://localhost:20128/api/shutdown` επιστρέφει 401 (διαδρομή που προστατεύεται πάντα) - [ ] Το `curl -H "host: evil.com" http://localhost:20128/api/mcp/sse` επιστρέφει 401 (προστασία loopback) - [ ] Το runtime του SQLite επιλύεται σε `bundled` κατά την πρώτη εκτέλεση (το ενσωματωμένο binary είναι έγκυρο για την πλατφόρμα) - [ ] Το runtime του SQLite υποχωρεί σε `runtime` όταν διαγραφεί το `node_modules/better-sqlite3` - [ ] Το έξυπνο φίλτρο MCP συμπιέζει πραγματική έξοδο του `playwright-mcp browser_snapshot` (μείωση ≥50%) - [ ] Και τα 10 αρχεία `skills/omniroute*/SKILL.md` είναι δημόσια προσβάσιμα μέσω raw URL του GitHub - [ ] Ο οδηγός αρχικής διαμόρφωσης εμφανίζει το βήμα περιήγησης στα επίπεδα "Πώς λειτουργεί" σε νέα εγκατάσταση - [ ] Το widget κάλυψης επιπέδων του αρχικού dashboard εμφανίζει το πλήθος των διαμορφωμένων/ενεργών στοιχείων --- ## Αποκοπή της 3.9.0 LTS (πρόβα στην 3.8.58) Μετά τη v3.8.59, η επόμενη έκδοση είναι η 3.9.0 και η κορυφή της μετατρέπεται σε δύο μακρόβιους κλάδους: `stable/v3` (η γραμμή v3 LTS, npm `latest`) και `develop` (v4, αναβαθμισμένη σε 4.0.0, npm `nightly`). Το μοντέλο κλάδων/καναλιών, το forward-port και οι ετικέτες βρίσκονται στο [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, προηγούμενο tag 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` και εμφανίζει ολόκληρη την ακολουθία — προϋποθέσεις (η προέλευση επιλύεται, το αποθετήριο προέλευσης έχει πλήρες ιστορικό — ένα shallow clone δεν μπορεί να προωθήσει το `stable/v3`, η πλευρά λήψης απορρίπτει το πακέτο στον πρώτο grafted γονέα, επομένως εκτελέστε την αποκοπή από ένα πλήρες clone ή εκτελέστε πρώτα `git fetch --unshallow origin` — το προηγούμενο tag υπάρχει, το `package.json` έχει την έκδοση-στόχο, υπάρχει ανοιχτό issue `release-freeze`, δεν υπάρχει ανοιχτό issue `Release branch not green` σε υπάρχοντα κλάδο έκδοσης — ένας κλάδος που δεν υπάρχει αναφέρεται ως `?` άγνωστος, ποτέ πράσινος — η ουρά `release` του Mergify είναι διαμορφωμένη (G11: `queue_rules`, `checks_timeout`, ετικέτα `queue`), το σύνολο κανόνων `release/*` εξακολουθεί να αποκλείει τη διαγραφή και το force-push και τα `stable/v3` και `develop` δεν υπάρχουν ακόμη), τα δύο βήματα δημιουργίας κλάδων, ποια εναύσματα ανενεργών workflow και ποιες συνθήκες `if:` γίνονται αληθείς (και ποια παραμένουν αποκλεισμένα από μια μεταβλητή αποθετηρίου ή καρφιτσωμένα στο κανονικό αποθετήριο), τα αναμενόμενα dist-tags (`latest` → 3.9.0, `next` και `nightly` κενά) και την επαναφορά. Κωδικός εξόδου `0` = `RESULT: READY`, `1` = αποτυχία προϋπόθεσης που εμποδίζει τη διαδικασία (`✗`), `2` = σφάλμα χρήσης. Το `--advisory ` υποβαθμίζει έναν έλεγχο σε προειδοποίηση (`!`) χωρίς να τον αποκρύπτει. Εκτελέστε τη δοκιμαστική εκτέλεση της πραγματικής αποκοπής όσο το πάγωμα έκδοσης της 3.9.0 παραμένει ανοιχτό — οι κλάδοι δημιουργούνται μετά το tag και πριν η Φάση 12c άρει το πάγωμα. ### Πρόβα της 3.8.58 (μόνο σε fork) ```bash # 1. Δοκιμαστική εκτέλεση στην τρέχουσα κορυφή με παραμέτρους πρόβας npm run release:dry-run-lts-cut -- --target-version 3.8.58 --previous-tag v3.8.57 \ --advisory freeze,base-green # 2. Εκτέλεση σε remote ενός FORK (το 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. Δοκιμή των ανενεργών 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 ``` Το commit αναβάθμισης του develop δημιουργείται με χαμηλού επιπέδου εντολές του git (χωρίς να επηρεάζεται το working tree) και αναβαθμίζει τα ίδια πέντε αρχεία με ένα commit ανοίγματος κύκλου: `package.json`, `open-sse/package.json`, `electron/package.json`, `package-lock.json` και `docs/openapi.yaml`. Η ενότητα `[4.0.0]` του CHANGELOG και τα αντίστοιχα i18n αντίγραφά της ανοίγονται κατόπιν στο `develop`, πριν από το πρώτο PR του. Το script δεν αλλάζει ποτέ τα npm dist-tags — κάντε πρόβα αυτών σε ένα δοκιμαστικό πακέτο. ### Artifact προεπισκόπησης PR (δημιουργία μία φορά, προώθηση των ίδιων byte) Το `.github/workflows/preview-artifact.yml` δημιουργεί ένα tarball παραγωγής από την κεφαλή ενός PR και επικυρώνει ακριβώς αυτό το build (τμήμα (a) του #8084). Μόνο 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` (SHA κεφαλής, SHA βάσης, hash του lockfile, πλατφόρμα, αρχιτεκτονική, ABI του node, bundler, πολιτική build — `scripts/release/artifact-identity.mjs`) και πιστοποιεί το tarball σε ξεχωριστό job. Η προώθηση μιας προεπισκόπησης σημαίνει εγκατάσταση αυτού του tarball: ποτέ μην εκτελείτε νέο build από τον πηγαίο κώδικα. ### Η αποκοπή (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` χειροκίνητα με τις εντολές που εμφανίζει η δοκιμαστική εκτέλεση — το script αρνείται να κάνει push στο `origin`. Για να επαναχρησιμοποιήσετε ένα ελεγμένο commit του develop, εκτελέστε πρώτα την πρόβα με `--execute` στην κορυφή της 3.9.0, χρησιμοποιώντας το fork σας· εμφανίζει και τα δύο SHA και μπορούν να γίνουν push τα ίδια commit: ```bash git push origin :refs/heads/stable/v3 :refs/heads/develop ``` 4. Προστατέψτε τα `stable/v3` και `develop` (rulesets + merge queue) πριν ενσωματωθεί το πρώτο PR. 5. Οι ανενεργές ροές εργασίας ενεργοποιούνται με την ύπαρξη των κλάδων: `forward-port.yml` (push στο `stable/v3`), `validate-stable-pr.yml` (PRs προς το `stable/v3`) και `nightly-v4-build.yml` (κάνει build το `develop`). Πριν από την έναρξη λειτουργίας, ορίστε το repository secret `secrets.FORWARD_PORT_TOKEN` (ώστε το CI να εκτελείται στα forward-port PRs)· η νυχτερινή δημοσίευση παραμένει απενεργοποιημένη μέχρι ο ιδιοκτήτης να ορίσει τη μεταβλητή repository `vars.NIGHTLY_PUBLISH` σε `true` και το npm Trusted Publishing να αποδεχτεί το `nightly-v4-build.yml`. Η επίλυση του καναλιού γίνεται από το `scripts/release/dist-tag.mjs`, το ίδιο resolver που χρησιμοποιεί το `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 ## Αυστηροί κανόνες - Ποτέ μην κάνετε commit απευθείας στο `main` - Ποτέ μη χρησιμοποιείτε `git push --force` στους κλάδους `main` ή `release/*` - Ποτέ μην παρακάμπτετε τα hooks του Husky (`--no-verify`) - Ποτέ μην κάνετε commit μυστικά, διαπιστευτήρια ή αρχεία `.env` - Η κάλυψη πρέπει να παραμένει ≥60/60/60/60 (εντολές/γραμμές/συναρτήσεις/κλάδοι) - Πάντα να συμπεριλαμβάνετε ή να ενημερώνετε δοκιμές όταν αλλάζετε κώδικα παραγωγής στα `src/`, `open-sse/`, `electron/` ή `bin/` ## Αυτοματοποιημένος έλεγχος συγχρονισμού Εκτελέστε το εργαλείο προστασίας συγχρονισμού της τεκμηρίωσης τοπικά πριν ανοίξετε ένα PR: ```bash npm run check:docs-sync ``` Το CI εκτελεί επίσης αυτόν τον έλεγχο στο `.github/workflows/ci.yml` (εργασία lint).