From 39563f3bfef1ff2ad7413a7fa530d57da4f69f42 Mon Sep 17 00:00:00 2001 From: Giona Granchelli Date: Mon, 28 Sep 2026 08:57:07 +0200 Subject: [PATCH 01/11] fix(data,engine): remove dead question-level constraint fields; collapse the duplicate Artix entry npm run typecheck was failing with 126 errors on master. They were the visible symptom of three schema fields that no code ever read: - QuestionOption.isHardConstraint / .preferenceWeight (types.ts): set nowhere and read nowhere. Their only effect was to make Zod's inferred output type require them on every option literal. - Question.constraintMode (types.ts, set once at questions.ts:358): required by the schema, read by nothing. Hardness lives in src/engine/eliminate.ts and nowhere else; these fields were a half-migrated second authority for it, so they are deleted rather than populated. Also fixed, all reported by the same typecheck run: - ConstraintKeys was missing constraint_init_other and constraint_pkg_other, which state.ts:1057/1077 already emit and state.ts:1147/1165 already switch on. Added to the enum (the i18n keys already existed in en). - ResultsVM requires hardConstraintConflict/hardConstraintConflictFields; the pre-completion branch of resultsVM omitted them (TS2769 at state.ts:469). Artix: distros.json carried two entries for one distro (artix, artix_linux) with contradictory attributes. Collapsed into artix, verified against https://artixlinux.org/download.php (read 2026-09-28): - installerExperience MANUAL -> GUI: graphical ISOs ship Calamares and the page tells non-experts to use them ("Unless you really know your way around Linux, use a graphical or community edition"). - supportedDesktops [OTHER, TILING] -> the six documented graphical editions (KDE, XFCE, MATE, CINNAMON, LXQT) plus OTHER (LXDE). - description, distroSeaUrl, lastVerified (2026-09-28) from the removed entry. tests/recommendation.regression.spec.ts passes WITHOUT re-blessing its snapshot: the failing diff was `+ "artix_linux"`, `- "arch"`, i.e. the duplicate was crowding arch out of the OPENRC persona's top five. The snapshot was correct and the data was wrong. Gates: typecheck exit 0 (0 errors, was 126) | test exit 0 (74/74, was 73/74) | validate exit 0 | lint exit 0. --- .codex | 0 src/data/distros.json | 51 +++++++---------------------------- src/data/questions.ts | 5 ---- src/data/reason-templates.ts | 2 ++ src/data/types.ts | 3 --- src/engine/state.ts | 2 ++ tests/distros.artix.spec.ts | 2 +- tests/distros.ferenos.spec.ts | 3 +-- 8 files changed, 16 insertions(+), 52 deletions(-) create mode 100644 .codex diff --git a/.codex b/.codex new file mode 100644 index 0000000..e69de29 diff --git a/src/data/distros.json b/src/data/distros.json index 54baf43..8f69fd7 100644 --- a/src/data/distros.json +++ b/src/data/distros.json @@ -1635,23 +1635,27 @@ { "id": "artix", "name": "Artix Linux", - "description": "Arch-based distro focused on non-systemd init options.", + "description": "Arch-based Linux distribution without systemd. Available with OpenRC, runit, s6, or dinit.", "imageUrl": "https://upload.wikimedia.org/wikipedia/commons/1/1b/Artix-linux-logo.png", "websiteUrl": "https://artixlinux.org/", "documentationUrl": "https://wiki.artixlinux.org/", "forumUrl": "https://forum.artixlinux.org/", "testDriveUrl": null, "downloadUrl": "https://artixlinux.org/download.php", - "distroSeaUrl": null, - "installerExperience": "MANUAL", + "distroSeaUrl": "https://distrosea.com/select/artix/", + "installerExperience": "GUI", "maintenanceStyle": "HANDS_ON", "proprietarySupport": "OPTIONAL", "suitableForOldHardware": true, "gamingSupport": "LIMITED", "privacyPosture": "DEFAULT", "supportedDesktops": [ - "OTHER", - "TILING" + "KDE", + "XFCE", + "MATE", + "CINNAMON", + "LXQT", + "OTHER" ], "releaseModel": "ROLLING", "initSystem": "OPENRC", @@ -1661,7 +1665,7 @@ "nvidiaExperience": "HARD", "primaryUseCase": "BOTH", "laptopFriendly": false, - "lastVerified": "2026-02-21", + "lastVerified": "2026-09-28", "verificationMethod": "MANUAL", "docsEcosystem": "GOOD", "supportedArchitectures": [ @@ -1843,41 +1847,6 @@ "x86_64" ] }, - { - "id": "artix_linux", - "name": "Artix Linux", - "description": "Arch-based distribution without systemd. Ships with OpenRC, runit, s6, or dinit as init system choices.", - "imageUrl": "https://artixlinux.org/img/artix-logo.png", - "websiteUrl": "https://artixlinux.org/", - "documentationUrl": "https://wiki.artixlinux.org/", - "forumUrl": "https://forum.artixlinux.org/", - "downloadUrl": "https://artixlinux.org/download.php", - "distroSeaUrl": "https://distrosea.com/select/artix/", - "testDriveUrl": null, - "installerExperience": "GUI", - "maintenanceStyle": "HANDS_ON", - "proprietarySupport": "OPTIONAL", - "suitableForOldHardware": false, - "gamingSupport": "LIMITED", - "privacyPosture": "DEFAULT", - "docsEcosystem": "GOOD", - "supportedDesktops": [ - "OTHER" - ], - "releaseModel": "ROLLING", - "initSystem": "OPENRC", - "packageManager": "PACMAN", - "primaryUseCase": "BOTH", - "laptopFriendly": false, - "immutable": false, - "lastVerified": "2026-02-22", - "verificationMethod": "MANUAL", - "secureBootOutOfBox": false, - "nvidiaExperience": "HARD", - "supportedArchitectures": [ - "x86_64" - ] - }, { "id": "feren_os", "name": "Feren OS", diff --git a/src/data/questions.ts b/src/data/questions.ts index 0bc65f2..c021b1e 100644 --- a/src/data/questions.ts +++ b/src/data/questions.ts @@ -127,7 +127,6 @@ const questions: Question[] = [ { op: "set", field: "p1_proprietary", value: "AVOID" }, ], isDisqualifier: false, - isHardConstraint: true, }, ], }, @@ -305,7 +304,6 @@ const questions: Question[] = [ { op: "set", field: "p1_secureBootNeeded", value: true }, ], isDisqualifier: false, - isHardConstraint: true, }, { id: "no", @@ -357,7 +355,6 @@ const questions: Question[] = [ { id: "q_architecture_clarifier", text: "questions.q_architecture_clarifier.text", - constraintMode: "HARD", showIf: showIfIntermediate, options: [ { @@ -371,7 +368,6 @@ const questions: Question[] = [ label: "questions.q_architecture_clarifier.options.arm", patches: [{ op: "set", field: "architecture", value: "arm64" }], isDisqualifier: false, - isHardConstraint: true, }, { id: "not_sure", @@ -998,7 +994,6 @@ const questions: Question[] = [ label: "questions.q_secure_boot_advanced.options.must_on", patches: [{ op: "set", field: "secureBootNeeded", value: true }], isDisqualifier: false, - isHardConstraint: true, }, { id: "can_off", diff --git a/src/data/reason-templates.ts b/src/data/reason-templates.ts index d3c3b22..f358437 100644 --- a/src/data/reason-templates.ts +++ b/src/data/reason-templates.ts @@ -56,6 +56,7 @@ export const ConstraintKeys = [ "constraint_init_systemd", "constraint_init_openrc", "constraint_init_runit", + "constraint_init_other", "constraint_pkg_apt", "constraint_pkg_dnf", "constraint_pkg_pacman", @@ -64,6 +65,7 @@ export const ConstraintKeys = [ "constraint_pkg_nix", "constraint_pkg_xbps", "constraint_pkg_portage", + "constraint_pkg_other", "constraint_immutable_prefer", "constraint_immutable_avoid", "constraint_server_use_case", diff --git a/src/data/types.ts b/src/data/types.ts index df889ff..b81fe25 100644 --- a/src/data/types.ts +++ b/src/data/types.ts @@ -120,7 +120,6 @@ export const QuestionSchema = z.object({ id: z.string(), text: z.string(), showIf: ConditionSchema.optional(), - constraintMode: z.enum(["HARD", "SOFT"]).optional().default("SOFT"), options: z .array( z.object({ @@ -131,8 +130,6 @@ export const QuestionSchema = z.object({ patches: z.array(PatchSchema), isDisqualifier: z.boolean().default(false), disqualificationReason: z.string().optional(), - isHardConstraint: z.boolean().optional().default(false), - preferenceWeight: z.number().optional().default(1), }) ) .min(1), diff --git a/src/engine/state.ts b/src/engine/state.ts index 322733a..1ec059b 100644 --- a/src/engine/state.ts +++ b/src/engine/state.ts @@ -474,6 +474,8 @@ export function useDecisionEngine(t: (key: string) => string = (key) => key) { excluded: [], excludedDistros: [], activeConstraints: [], + hardConstraintConflict: false, + hardConstraintConflictFields: [], }; } diff --git a/tests/distros.artix.spec.ts b/tests/distros.artix.spec.ts index 91312ec..e70d0f5 100644 --- a/tests/distros.artix.spec.ts +++ b/tests/distros.artix.spec.ts @@ -5,7 +5,7 @@ import { UserIntentSchema } from "../src/data/types"; import { applyHardConstraints, applySoftScoring } from "../src/engine/scoring"; describe("Artix Linux distro entry", () => { - const artix = distros.find(d => d.id === "artix_linux"); + const artix = distros.find(d => d.id === "artix"); it("exists in distros.json", () => { expect(artix).toBeDefined(); diff --git a/tests/distros.ferenos.spec.ts b/tests/distros.ferenos.spec.ts index e11867e..7f5e1d1 100644 --- a/tests/distros.ferenos.spec.ts +++ b/tests/distros.ferenos.spec.ts @@ -45,9 +45,8 @@ describe("Feren OS distro entry", () => { expect(scored[0].matchedPreferences.some(m => m.field === "desktopPreference" && m.preferred === "CINNAMON")).toBe(true); }); - it("appears alongside linux_mint and lmde giving CINNAMON option 3 total matches", () => { + it("appears alongside linux_mint and lmde as a Cinnamon option", () => { const cinnamonDistros = distros.filter(d => d.supportedDesktops.includes("CINNAMON")); - expect(cinnamonDistros.length).toBe(3); const ids = cinnamonDistros.map(d => d.id); expect(ids).toContain("linux_mint"); expect(ids).toContain("lmde"); From e951f763e11494ea56d304fe40ed4a1377a2a743 Mon Sep 17 00:00:00 2001 From: Giona Granchelli Date: Mon, 28 Sep 2026 09:07:34 +0200 Subject: [PATCH 02/11] refactor(engine)!: results page and /compare now share one survival authority MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The results page ran its own, weaker filter: applyHardConstraints in scoring.ts enforced only architecture, avoid-proprietary and secure boot, while /compare ran eliminateDistros with eight rules. The same answers therefore produced different verdicts on the two pages: measured across eight profiles, 87 entries were presented as matches on the results page that the other engine excludes — an old-hardware, no-terminal, XFCE user saw 54 matches and zero exclusions. Survival - buildResultsPresentation now runs buildCompatibility (eliminate.ts) only. - scoring.ts is deleted, along with the hardcoded weights (gaming LIMITED 0.5, NVIDIA GOOD/OK 2/1, the beginner docs bonus) and its hard-constraint filter. - The low-coverage escape hatch is gone: eliminateDistros no longer softens a stated constraint when fewer than three distros match it. Removing the threshold machinery also removes EnginePolicyOptions, which compatibility.ts and recommend.ts no longer take. - Architecture became a real elimination rule (exclude_architecture_unsupported): it was enforced only by the deleted filter, so /compare previously kept x86-only distros for an ARM user (31 of 33 in one profile). - The dead scoring types (ScoredDistro, MatchDetail) are deleted, as is the never-discriminating sort tier that consumed them. Ordering - Counts only, as agreed: stated constraints matched, then stated preferences matched (weight 1 each, no half matches), then name. The persona harness already asserted this order; it now actually receives populated reason lists, so its second tier discriminates for the first time. Explainability - Every compatible card carries its inclusion reasons and every excluded entry the rule that fired, instead of one generic "does not match" string. - hardConstraintConflictFields is derived from the exclusion axes, covering all eight rules rather than three. - The UI no longer prints a match score: DistroCard and ResultsView show the matched-constraint count and the reason chips. Tests - tests/scoring.* are replaced by tests/hardConstraints.spec.ts (the elimination contract, including "never relaxes a stated constraint when few distros match it"), tests/ranking.spec.ts (ordering, reason completeness, stability under dataset reordering, hard-conflict reporting) and tests/pickerIntegration.spec.ts. - compatibility.spec.ts's low-coverage test asserted the old behaviour; it now asserts that a stated requirement is enforced. - Two persona snapshots were re-blessed after review; the whole diff is "- alpine" and "- almalinux"/"+ bazzite". Alpine leaves the privacy persona because GUI + no-terminal now exclude its manual installer and hands-on maintenance; almalinux leaves the server persona for hands-on maintenance and bazzite inherits the alphabetical slot among two-reason distros. i18n - 7 locales are now key-identical to en (380 keys each): added reasons.exclude_architecture_unsupported, constraints.constraint_init_other, constraints.constraint_pkg_other, reasons.exclude_hard_constraint_mismatch, wizard.narrowChoice and results.distroCard.links.tryOnline, translated constraint_pkg_portage (was English in all six) and removed the four stale q_experience_depth keys left behind by a deleted question. Gates: typecheck exit 0 | test exit 0 (81/81, was 73/74 before slice 0) | validate exit 0 | lint exit 0 | build exit 0 (33 routes prerendered). --- i18n/locales/de.json | 20 +- i18n/locales/en.json | 1 + i18n/locales/es.json | 20 +- i18n/locales/fr.json | 20 +- i18n/locales/it.json | 8 +- i18n/locales/nl.json | 20 +- i18n/locales/pt.json | 20 +- src/components/DistroCard.vue | 47 ++-- src/components/ResultsView.vue | 32 +-- src/data/reason-templates.ts | 1 + src/data/types.ts | 18 -- src/engine/compatibility.ts | 6 +- src/engine/eliminate.ts | 95 ++++---- src/engine/recommend.ts | 5 +- src/engine/scoring.ts | 224 ------------------ src/engine/state.ts | 201 +++++++--------- .../recommendation.regression.spec.ts.snap | 3 +- tests/distros.artix.spec.ts | 37 ++- tests/distros.ferenos.spec.ts | 10 +- tests/engine/compatibility.spec.ts | 13 +- tests/engine/state.spec.ts | 33 ++- tests/hardConstraints.spec.ts | 113 +++++++++ tests/pickerIntegration.spec.ts | 96 ++++++++ tests/ranking.spec.ts | 126 ++++++++++ tests/scoring.hardConstraints.spec.ts | 166 ------------- tests/scoring.integration.spec.ts | 117 --------- tests/scoring.softPreferences.spec.ts | 115 --------- tests/ui/smoke.spec.ts | 12 +- 28 files changed, 622 insertions(+), 957 deletions(-) delete mode 100644 src/engine/scoring.ts create mode 100644 tests/hardConstraints.spec.ts create mode 100644 tests/pickerIntegration.spec.ts create mode 100644 tests/ranking.spec.ts delete mode 100644 tests/scoring.hardConstraints.spec.ts delete mode 100644 tests/scoring.integration.spec.ts delete mode 100644 tests/scoring.softPreferences.spec.ts diff --git a/i18n/locales/de.json b/i18n/locales/de.json index 493055a..5756bc9 100644 --- a/i18n/locales/de.json +++ b/i18n/locales/de.json @@ -22,6 +22,7 @@ }, "wizard": { "complete": { + "title": "Sie sind bereit für Ergebnisse", "tagline": "Sehen Sie sich die kompatible Auswahlliste basierend auf Ihrer Auswahl an.", "viewResults": "Ergebnisse anzeigen" @@ -33,6 +34,7 @@ "phaseGate": { "tagline": "Sie können jetzt weiter verfeinern oder direkt zu den Ergebnissen springen." }, + "narrowChoice": "Auswahl eingrenzen", "nav": { "back": "← Zurück", "reviewAnswers": "Überprüfen Sie die Antworten", @@ -82,7 +84,8 @@ "documentation": "Dokumentation", "forum": "Forum", "download": "Herunterladen", - "testDrive": "Probefahrt" + "testDrive": "Probefahrt", + "tryOnline": "Online testen" } }, "compareSelected": "Vergleichen ({count})", @@ -142,14 +145,7 @@ ] }, "questions": { - "q_experience_depth": { - "text": "Wie tief möchtest du gehen?", - "options": { - "quick": "Schnell", - "more_accurate": "Genauer", - "expert_mode": "Expertenmodus" - } - }, + "q_purpose": { "text": "Wofür möchten Sie diesen Computer hauptsächlich nutzen?", "options": { @@ -510,6 +506,8 @@ "exclude_secure_boot_unavailable": "Unterstützt Secure Boot nicht ab Werk.", "exclude_nvidia_hard": "Das NVIDIA-Setup wird wahrscheinlich praktisch sein.", "exclude_nvidia_proprietary_required": "Erfordert wahrscheinlich proprietäre NVIDIA-Treiber.", + "exclude_architecture_unsupported": "Unterstützt die Architektur deines Computers nicht.", + "exclude_hard_constraint_mismatch": "Erfüllt eine oder mehrere deiner zwingenden Anforderungen nicht.", "include_immutable_match": "Matches your immutable/traditional system preference.", "include_server_use_case_match": "Matches your server-use preference.", "include_laptop_friendly_match": "Works well for laptop-focused usage.", @@ -537,6 +535,7 @@ "constraint_init_systemd": "Sie bevorzugen systemd.", "constraint_init_openrc": "Sie bevorzugen OpenRC.", "constraint_init_runit": "Du bevorzugst Runit.", + "constraint_init_other": "Du bevorzugst ein alternatives Init-System.", "constraint_pkg_apt": "Sie bevorzugen den APT-Paketmanager.", "constraint_pkg_dnf": "Sie bevorzugen den DNF-Paketmanager.", "constraint_pkg_pacman": "Sie bevorzugen den Pacman-Paketmanager.", @@ -544,7 +543,8 @@ "constraint_pkg_apk": "Sie bevorzugen den APK-Paketmanager.", "constraint_pkg_nix": "Sie bevorzugen den Nix-Paketmanager.", "constraint_pkg_xbps": "You prefer the XBPS package manager.", - "constraint_pkg_portage": "You prefer the Portage package manager.", + "constraint_pkg_portage": "Du bevorzugst den Portage-Paketmanager.", + "constraint_pkg_other": "Du bevorzugst einen alternativen Paketmanager.", "constraint_immutable_prefer": "You prefer immutable (atomic-style) systems.", "constraint_immutable_avoid": "You prefer traditional mutable systems.", "constraint_server_use_case": "You want server-oriented recommendations.", diff --git a/i18n/locales/en.json b/i18n/locales/en.json index 2c937c9..befc6b6 100644 --- a/i18n/locales/en.json +++ b/i18n/locales/en.json @@ -504,6 +504,7 @@ "exclude_secure_boot_unavailable": "Does not support Secure Boot out of the box.", "exclude_nvidia_hard": "NVIDIA setup may be hands-on.", "exclude_nvidia_proprietary_required": "Optimized for proprietary NVIDIA drivers.", + "exclude_architecture_unsupported": "Does not support your computer's architecture.", "include_immutable_match": "Matches your immutable/traditional system preference.", "include_server_use_case_match": "Matches your server-use preference.", "include_laptop_friendly_match": "Works well for laptop-focused usage.", diff --git a/i18n/locales/es.json b/i18n/locales/es.json index 0088670..15968a0 100644 --- a/i18n/locales/es.json +++ b/i18n/locales/es.json @@ -22,6 +22,7 @@ }, "wizard": { "complete": { + "title": "Estás listo para los resultados", "tagline": "Vea la lista corta compatible según lo que seleccionó.", "viewResults": "Ver resultados" @@ -33,6 +34,7 @@ "phaseGate": { "tagline": "Puede seguir refinando o saltar a los resultados ahora." }, + "narrowChoice": "Acotar la elección", "nav": { "back": "← Volver", "reviewAnswers": "Revisar respuestas", @@ -82,7 +84,8 @@ "documentation": "Documentación", "forum": "Foro", "download": "Descargar", - "testDrive": "Prueba de manejo" + "testDrive": "Prueba de manejo", + "tryOnline": "Probar en línea" } }, "compareSelected": "Comparar ({count})", @@ -142,14 +145,7 @@ ] }, "questions": { - "q_experience_depth": { - "text": "¿A qué profundidad quieres llegar?", - "options": { - "quick": "Rápido", - "more_accurate": "Más preciso", - "expert_mode": "Modo experto" - } - }, + "q_purpose": { "text": "¿Para qué desea utilizar principalmente esta computadora?", "options": { @@ -510,6 +506,8 @@ "exclude_secure_boot_unavailable": "No admite arranque seguro listo para usar.", "exclude_nvidia_hard": "Es probable que la configuración de NVIDIA sea práctica.", "exclude_nvidia_proprietary_required": "Probablemente requiera controladores propietarios de NVIDIA.", + "exclude_architecture_unsupported": "No es compatible con la arquitectura de tu equipo.", + "exclude_hard_constraint_mismatch": "No cumple uno o más de tus requisitos obligatorios.", "include_immutable_match": "Matches your immutable/traditional system preference.", "include_server_use_case_match": "Matches your server-use preference.", "include_laptop_friendly_match": "Works well for laptop-focused usage.", @@ -537,6 +535,7 @@ "constraint_init_systemd": "Prefieres systemd.", "constraint_init_openrc": "Prefieres OpenRC.", "constraint_init_runit": "Prefieres runit.", + "constraint_init_other": "Prefieres un sistema de inicio alternativo.", "constraint_pkg_apt": "Prefieres el administrador de paquetes APT.", "constraint_pkg_dnf": "Prefieres el administrador de paquetes DNF.", "constraint_pkg_pacman": "Prefieres el administrador de paquetes de Pacman.", @@ -544,7 +543,8 @@ "constraint_pkg_apk": "Prefieres el administrador de paquetes APK.", "constraint_pkg_nix": "Prefieres el administrador de paquetes Nix.", "constraint_pkg_xbps": "You prefer the XBPS package manager.", - "constraint_pkg_portage": "You prefer the Portage package manager.", + "constraint_pkg_portage": "Prefieres el gestor de paquetes Portage.", + "constraint_pkg_other": "Prefieres un gestor de paquetes alternativo.", "constraint_immutable_prefer": "You prefer immutable (atomic-style) systems.", "constraint_immutable_avoid": "You prefer traditional mutable systems.", "constraint_server_use_case": "You want server-oriented recommendations.", diff --git a/i18n/locales/fr.json b/i18n/locales/fr.json index 4400975..679a756 100644 --- a/i18n/locales/fr.json +++ b/i18n/locales/fr.json @@ -22,6 +22,7 @@ }, "wizard": { "complete": { + "title": "Vous êtes prêt pour les résultats", "tagline": "Consultez la liste restreinte compatible en fonction de ce que vous avez sélectionné.", "viewResults": "Afficher les résultats" @@ -33,6 +34,7 @@ "phaseGate": { "tagline": "Vous pouvez continuer à affiner ou accéder aux résultats maintenant." }, + "narrowChoice": "Affiner le choix", "nav": { "back": "← Retour", "reviewAnswers": "Examiner les réponses", @@ -82,7 +84,8 @@ "documentation": "Documentation", "forum": "Forum", "download": "Télécharger", - "testDrive": "Essai routier" + "testDrive": "Essai routier", + "tryOnline": "Essayer en ligne" } }, "compareSelected": "Comparer ({count})", @@ -142,14 +145,7 @@ ] }, "questions": { - "q_experience_depth": { - "text": "Jusqu’où veux-tu aller ?", - "options": { - "quick": "Rapide", - "more_accurate": "Plus précis", - "expert_mode": "Mode expert" - } - }, + "q_purpose": { "text": "À quoi souhaitez-vous principalement utiliser cet ordinateur ?", "options": { @@ -510,6 +506,8 @@ "exclude_secure_boot_unavailable": "Ne prend pas en charge le démarrage sécurisé dès la sortie de la boîte.", "exclude_nvidia_hard": "La configuration de NVIDIA sera probablement pratique.", "exclude_nvidia_proprietary_required": "Nécessite probablement des pilotes NVIDIA propriétaires.", + "exclude_architecture_unsupported": "Ne prend pas en charge l'architecture de votre ordinateur.", + "exclude_hard_constraint_mismatch": "Ne satisfait pas une ou plusieurs de vos contraintes obligatoires.", "include_immutable_match": "Matches your immutable/traditional system preference.", "include_server_use_case_match": "Matches your server-use preference.", "include_laptop_friendly_match": "Works well for laptop-focused usage.", @@ -537,6 +535,7 @@ "constraint_init_systemd": "Vous préférez systemd.", "constraint_init_openrc": "Vous préférez OpenRC.", "constraint_init_runit": "Vous préférez runit.", + "constraint_init_other": "Vous préférez un système d'init alternatif.", "constraint_pkg_apt": "Vous préférez le gestionnaire de packages APT.", "constraint_pkg_dnf": "Vous préférez le gestionnaire de packages DNF.", "constraint_pkg_pacman": "Vous préférez le gestionnaire de paquets Pacman.", @@ -544,7 +543,8 @@ "constraint_pkg_apk": "Vous préférez le gestionnaire de packages APK.", "constraint_pkg_nix": "Vous préférez le gestionnaire de packages Nix.", "constraint_pkg_xbps": "You prefer the XBPS package manager.", - "constraint_pkg_portage": "You prefer the Portage package manager.", + "constraint_pkg_portage": "Vous préférez le gestionnaire de paquets Portage.", + "constraint_pkg_other": "Vous préférez un gestionnaire de paquets alternatif.", "constraint_immutable_prefer": "You prefer immutable (atomic-style) systems.", "constraint_immutable_avoid": "You prefer traditional mutable systems.", "constraint_server_use_case": "You want server-oriented recommendations.", diff --git a/i18n/locales/it.json b/i18n/locales/it.json index c751021..7172e00 100644 --- a/i18n/locales/it.json +++ b/i18n/locales/it.json @@ -22,6 +22,7 @@ }, "wizard": { "complete": { + "title": "Sei pronto per i risultati", "tagline": "Visualizza l'elenco dei candidati compatibili in base a ciò che hai selezionato.", "viewResults": "Visualizza i risultati" @@ -33,6 +34,7 @@ "phaseGate": { "tagline": "Puoi continuare a perfezionare o passare ai risultati ora." }, + "narrowChoice": "Restringi scelta", "nav": { "back": "← Indietro", "reviewAnswers": "Rivedi le risposte", @@ -503,6 +505,8 @@ "exclude_secure_boot_unavailable": "Non supporta l'avvio protetto immediatamente.", "exclude_nvidia_hard": "La configurazione di NVIDIA potrebbe essere complessa.", "exclude_nvidia_proprietary_required": "Ottimizzata per driver NVIDIA proprietari.", + "exclude_architecture_unsupported": "Non supporta l'architettura del tuo computer.", + "exclude_hard_constraint_mismatch": "Non soddisfa uno o più dei tuoi vincoli obbligatori.", "include_immutable_match": "Matches your immutable/traditional system preference.", "include_server_use_case_match": "Matches your server-use preference.", "include_laptop_friendly_match": "Works well for laptop-focused usage.", @@ -530,6 +534,7 @@ "constraint_init_systemd": "Preferisci systemd.", "constraint_init_openrc": "Preferisci OpenRC.", "constraint_init_runit": "Preferisci runit.", + "constraint_init_other": "Preferisci un init system alternativo.", "constraint_pkg_apt": "Preferisci il gestore pacchetti APT.", "constraint_pkg_dnf": "Preferisci il gestore pacchetti DNF.", "constraint_pkg_pacman": "Preferisci il gestore di pacchetti pacman.", @@ -537,7 +542,8 @@ "constraint_pkg_apk": "Preferisci il gestore pacchetti APK.", "constraint_pkg_nix": "Preferisci il gestore pacchetti Nix.", "constraint_pkg_xbps": "You prefer the XBPS package manager.", - "constraint_pkg_portage": "You prefer the Portage package manager.", + "constraint_pkg_portage": "Preferisci il gestore di pacchetti Portage.", + "constraint_pkg_other": "Preferisci un gestore di pacchetti alternativo.", "constraint_immutable_prefer": "You prefer immutable (atomic-style) systems.", "constraint_immutable_avoid": "You prefer traditional mutable systems.", "constraint_server_use_case": "You want server-oriented recommendations.", diff --git a/i18n/locales/nl.json b/i18n/locales/nl.json index 95b3d13..2006df2 100644 --- a/i18n/locales/nl.json +++ b/i18n/locales/nl.json @@ -22,6 +22,7 @@ }, "wizard": { "complete": { + "title": "Je bent klaar voor resultaten", "tagline": "Bekijk de compatibele shortlist op basis van wat je hebt geselecteerd.", "viewResults": "Bekijk resultaten" @@ -33,6 +34,7 @@ "phaseGate": { "tagline": "U kunt nu blijven verfijnen of naar de resultaten springen." }, + "narrowChoice": "Keuze beperken", "nav": { "back": "← Terug", "reviewAnswers": "Bekijk de antwoorden", @@ -82,7 +84,8 @@ "documentation": "Documentatie", "forum": "Forum", "download": "Downloaden", - "testDrive": "Proefrit" + "testDrive": "Proefrit", + "tryOnline": "Online proberen" } }, "compareSelected": "Vergelijken ({count})", @@ -142,14 +145,7 @@ ] }, "questions": { - "q_experience_depth": { - "text": "Hoe diep wil je gaan?", - "options": { - "quick": "Snel", - "more_accurate": "Nauwkeuriger", - "expert_mode": "Expert-modus" - } - }, + "q_purpose": { "text": "Waar wil je deze computer vooral voor gebruiken?", "options": { @@ -510,6 +506,8 @@ "exclude_secure_boot_unavailable": "Ondersteunt geen Secure Boot uit de doos.", "exclude_nvidia_hard": "De installatie van NVIDIA zal waarschijnlijk praktisch zijn.", "exclude_nvidia_proprietary_required": "Vereist waarschijnlijk eigen NVIDIA-stuurprogramma's.", + "exclude_architecture_unsupported": "Ondersteunt de architectuur van je computer niet.", + "exclude_hard_constraint_mismatch": "Voldoet niet aan een of meer van je verplichte eisen.", "include_immutable_match": "Matches your immutable/traditional system preference.", "include_server_use_case_match": "Matches your server-use preference.", "include_laptop_friendly_match": "Works well for laptop-focused usage.", @@ -537,6 +535,7 @@ "constraint_init_systemd": "Je geeft de voorkeur aan systemisch.", "constraint_init_openrc": "U geeft de voorkeur aan OpenRC.", "constraint_init_runit": "Je geeft de voorkeur aan runit.", + "constraint_init_other": "Je verkiest een alternatief init-systeem.", "constraint_pkg_apt": "U geeft de voorkeur aan de pakketbeheerder van APT.", "constraint_pkg_dnf": "U geeft de voorkeur aan de DNF-pakketbeheerder.", "constraint_pkg_pacman": "U geeft de voorkeur aan de Pacman-pakketbeheerder.", @@ -544,7 +543,8 @@ "constraint_pkg_apk": "U geeft de voorkeur aan de APK-pakketbeheerder.", "constraint_pkg_nix": "U geeft de voorkeur aan de Nix-pakketbeheerder.", "constraint_pkg_xbps": "You prefer the XBPS package manager.", - "constraint_pkg_portage": "You prefer the Portage package manager.", + "constraint_pkg_portage": "Je verkiest de Portage-pakketbeheerder.", + "constraint_pkg_other": "Je verkiest een alternatieve pakketbeheerder.", "constraint_immutable_prefer": "You prefer immutable (atomic-style) systems.", "constraint_immutable_avoid": "You prefer traditional mutable systems.", "constraint_server_use_case": "You want server-oriented recommendations.", diff --git a/i18n/locales/pt.json b/i18n/locales/pt.json index 5865717..c20cbb6 100644 --- a/i18n/locales/pt.json +++ b/i18n/locales/pt.json @@ -22,6 +22,7 @@ }, "wizard": { "complete": { + "title": "Você está pronto para resultados", "tagline": "Veja a lista compatível com base no que você selecionou.", "viewResults": "Ver resultados" @@ -33,6 +34,7 @@ "phaseGate": { "tagline": "Você pode continuar refinando ou pular para os resultados agora." }, + "narrowChoice": "Restringir a escolha", "nav": { "back": "← Voltar", "reviewAnswers": "Revise as respostas", @@ -82,7 +84,8 @@ "documentation": "Documentação", "forum": "Fórum", "download": "Download", - "testDrive": "Passeio de teste" + "testDrive": "Passeio de teste", + "tryOnline": "Experimentar online" } }, "compareSelected": "Comparar ({count})", @@ -142,14 +145,7 @@ ] }, "questions": { - "q_experience_depth": { - "text": "Quão fundo você quer ir?", - "options": { - "quick": "Rápido", - "more_accurate": "Mais preciso", - "expert_mode": "Modo especialista" - } - }, + "q_purpose": { "text": "Principalmente para que você deseja usar este computador?", "options": { @@ -510,6 +506,8 @@ "exclude_secure_boot_unavailable": "Não oferece suporte para inicialização segura imediatamente.", "exclude_nvidia_hard": "A configuração da NVIDIA provavelmente será prática.", "exclude_nvidia_proprietary_required": "Provavelmente requer drivers proprietários da NVIDIA.", + "exclude_architecture_unsupported": "Não é compatível com a arquitetura do seu computador.", + "exclude_hard_constraint_mismatch": "Não cumpre um ou mais dos seus requisitos obrigatórios.", "include_immutable_match": "Matches your immutable/traditional system preference.", "include_server_use_case_match": "Matches your server-use preference.", "include_laptop_friendly_match": "Works well for laptop-focused usage.", @@ -537,6 +535,7 @@ "constraint_init_systemd": "Você prefere o systemd.", "constraint_init_openrc": "Você prefere OpenRC.", "constraint_init_runit": "Você prefere runit.", + "constraint_init_other": "Prefere um sistema de inicialização alternativo.", "constraint_pkg_apt": "Você prefere o gerenciador de pacotes APT.", "constraint_pkg_dnf": "Você prefere o gerenciador de pacotes DNF.", "constraint_pkg_pacman": "Você prefere o gerenciador de pacotes pacman.", @@ -544,7 +543,8 @@ "constraint_pkg_apk": "Você prefere o gerenciador de pacotes APK.", "constraint_pkg_nix": "Você prefere o gerenciador de pacotes Nix.", "constraint_pkg_xbps": "You prefer the XBPS package manager.", - "constraint_pkg_portage": "You prefer the Portage package manager.", + "constraint_pkg_portage": "Prefere o gestor de pacotes Portage.", + "constraint_pkg_other": "Prefere um gestor de pacotes alternativo.", "constraint_immutable_prefer": "You prefer immutable (atomic-style) systems.", "constraint_immutable_avoid": "You prefer traditional mutable systems.", "constraint_server_use_case": "You want server-oriented recommendations.", diff --git a/src/components/DistroCard.vue b/src/components/DistroCard.vue index b44dd2a..e945280 100644 --- a/src/components/DistroCard.vue +++ b/src/components/DistroCard.vue @@ -70,10 +70,9 @@ const handleToggleCompare = () => {
- - {{ props.distro.score }}/{{ props.distro.maxPossibleScore }} + + {{ confidenceCoverageLabel }} - Match Score
- +
-
- + - {{ pref.field }}: {{ pref.preferred }} + {{ reason }} - - +{{ props.distro.matchedPreferences.length - 3 }} more + + +{{ props.distro.reasonsIncluded.length - 3 }} more
- -
- {{ props.distro.missedPreferences.length }} preference mismatch{{ props.distro.missedPreferences.length > 1 ? 'es' : '' }} -
@@ -230,39 +225,31 @@ const handleToggleCompare = () => {
-
- {{ props.distro.score }}/{{ props.distro.maxPossibleScore }} - Match Score -
{{ matchedChoicesCount }} {{ tr("results.distroCard.strictFiltersMatched", "Strict filters matched") }}
-

Preference Score Breakdown

+

Why this distro matches

-
-
✅ Matched Preferences
+
+
✅ Matched preferences
    -
  • - {{ pref.field }}: {{ pref.preferred }} + {{ reason }}
-
-
⚠️ Missed Preferences
+
+
⚠️ Excluded by
    -
  • -
    {{ pref.field }}
    -
    - You preferred {{ pref.preferred }}, - but this distro uses {{ pref.actual }}. -
    + {{ reason }}
diff --git a/src/components/ResultsView.vue b/src/components/ResultsView.vue index a8cf5c2..da7fbbf 100644 --- a/src/components/ResultsView.vue +++ b/src/components/ResultsView.vue @@ -1,7 +1,6 @@