Repository navigation
feat: configurar y detectar el entorno WSL en Windows #90
Description
Pre-flight checks
- I searched existing issues and found no duplicate.
- I understand that this proposal requires product review before implementation.
La búsqueda de duplicados abiertos y cerrados fue realizada por el asistente. El mantenedor confirmó el principio de revisión de producto y aprobó la propuesta quorb-wsl-v1 y su publicación. La publicación no inicia implementación ni asigna trabajo.
Problem to solve
Quorb para Windows resuelve por defecto las sesiones CLI desde el entorno Windows. Un usuario con Codex, Gemini o Claude en WSL debe introducir rutas manuales y no puede seleccionar de forma coherente el entorno.
Proposed solution
Persistir una integración WSL explícita, desactivada por defecto, con distribución elegida. Enumerar distribuciones y resolver el usuario predeterminado y su home real mediante operaciones acotadas; no asumir que el usuario Windows coincide con el Linux ni construir el home a partir de su nombre. Exponer metadatos de entorno y diagnóstico para Ajustes, no contenidos de credenciales.
Affected area
Application behavior
Scope and non-goals
Objetivo y alcance
Resultado: seleccionar y describir un entorno de sesión CLI Windows o WSL de forma persistente y verificable. Visible/operativo únicamente en Windows. Conservar configuración antigua y datos propios de Quorb en Windows; no sustituir el home global de la aplicación.
Dependencias y decisiones
Ninguna dependencia técnica externa. Cerrar W0 antes de desarrollar: contrato de entorno, distribución seleccionada, política de activación de distribuciones detenidas y estrategia de shell para detección/login. Enumerar no debe despertar distribuciones silenciosamente; conectar, comprobar o iniciar login debe informar antes de iniciar una distribución detenida y requerir una acción explícita del usuario.
Criterios de aceptación
- Configuración ausente/antigua conserva modo Windows y todos los demás datos.
- Modo y distribución persisten, se sanea configuración inválida y se distingue una distribución previamente elegida pero ya no disponible.
- Distribuciones/estado y home del usuario predeterminado se resuelven sin asumir nombres/rutas ni instalar herramientas.
- Diagnóstico distingue WSL ausente, cero distribuciones, distribución detenida/eliminada, salida inválida y timeout.
- Procesos y acceso al filesystem tienen límites; no bloquean el hilo de UI ni despiertan una distribución por polling.
- Los datos/configuración/historial propios de Quorb conservan ubicación Windows.
- Tests deterministas con descubrimiento/procesos simulados cubren persistencia, configuración antigua, errores, varias distribuciones y nombres con espacios/no ASCII.
- Evidencia Windows/WSL real de descubrimiento y recuperación, sin afirmar compatibilidad no comprobada.
Orientación
Entradas: src-tauri/src/config.rs, comandos Tauri en src-tauri/src/lib.rs, src/lib/types.ts y resolución compartida de entorno CLI. Aislar la integración Windows/WSL para no alterar Windows nativo ni el futuro port macOS.
ODD cercano
| Fase | Resultado | Dependencias | Validación y salida |
|---|---|---|---|
| Observar W0 | Inventario de configuración, cuentas, login/detección y comportamiento WSL real | Ninguna | Evidencia trazable, matriz de casos y discrepancias registradas |
| Decidir W1 | Contrato de entorno y políticas de activación, shell, errores y límites | W0 | Decisiones aceptadas antes de implementar |
| Desarrollar W2 | Persistencia/discovery con adaptadores inyectables | W1 | RED/GREEN aplicable para defaults, configuración antigua y errores |
| Verificar W3 | Contrato funcional y baseline Windows/WSL | W2 | Suite pertinente y evidencia real; límites explícitos |
Exclusiones
No Linux nativo, Antigravity, instalación/gestión de WSL o CLI, descubrimiento de todos los usuarios Linux, cambios de visibilidad, firma ni releases.
Coordinación y entrega
Parte de quorb-wsl-v1, milestone «Integración WSL en Windows» e índice #45. Estado: planificada; no anunciar lista para implementar mientras falten las decisiones o dependencias indicadas. Sin assignee inicial. Revalidar issue, comentarios, responsables y PR antes de un inicio explícito; asignación no es un lock. Se conserva la prioridad vigente del roadmap: #66 sigue siendo el primer objetivo nuevo recomendado y WSL puede investigarse independientemente sin desplazar compromisos existentes.
Tests y documentación con cada unidad. Seguir CONTRIBUTING y entregar cambios revisables; checks planificados, no ejecutados durante esta planificación: npm test, npm run typecheck, npm run build y cargo test en src-tauri, según superficie. Linux no acredita ejecución Windows/WSL. Commit, push, PR, merge, firma, release y asignaciones requieren sus autorizaciones propias.
Alternatives considered
Rutas UNC manuales: ya disponibles, pero no constituyen un modo de entorno. Autodetección silenciosa/fallback entre Windows y WSL: descartados por ambigüedad entre cuentas. Soporte Linux nativo: no necesario para integrar una app Windows con WSL.
Activity
docs(w0): prepare F7-F10 evidence steps (UNC wake, shell, wsl.exe pat…
docs(w0): F7-F10 evidence steps (UNC wake, shell, wsl.exe path, stdin) (
docs(wsl-lab): W0 evidence F7-F10 (egdev6#90)
docs(wsl-lab): W0 evidence with F1-F10 findings and W1 input decisions (
sosan commentedon Oct 18, 2026
@egdev6,
W0 queda con evidencia ejecutada en runner real (
windows-latest, Server 2025), sin pedir asignación ni proponer PR (sigo el flujo ODD de #90: "Sin assignee inicial; revalidar issue, comentarios, responsables y PR antes de un inicio explícito").Rama:
investigacion/w0-wsl-lab(en mi forksosan/quorb), commit8fbecf3sobre80b0810(main). Tres archivos: dos workflows (.github/workflows/w0-evidence.yml,.github/workflows/w0-names.yml) y un doc (docs/w0-wsl-lab/W0-EVIDENCE.md).Runs reproducibles:
39129860995— w0-evidence (artifactw0-evidence.zip≈ 13.3 KB / 39 archivos). Cubre F1–F10.39124241492— w0-names (artifactw0-names-evidence.zip≈ 2.2 KB / 5 archivos). Matriz de nombres.F1–F6 (evidencia en detalle)
F1 — Codificación dual de salida. Sin
WSL_UTF8=1,wsl.exe --status / --version / --listescribe UTF-16LE sin BOM a un fichero redirigido (capturado en bytes crudos + hex head:hex-head-list-verbose.txt,encoding-shape.txt). ConWSL_UTF8=1la salida es UTF-8 plano. Quorb debe fijarWSL_UTF8=1para los procesos hijo o decodificar ambos formatos; un parseo naive por líneas de la salida default produce texto con\x00intercalado.F2 — Exit codes ruidosos y no documentados.
wsl --list --allcon distros instaladasexit-codes.txtwsl --list --allcon cero distrosexit-codes.txtwsl --list --verbosecon cero distroslist-verbose-default.txtwsl -d <missing>Wsl/Service/WSL_E_DISTRO_NOT_FOUNDzero-distro-missing.txtInvalid command line argumentexit-codes.txt-d " ")exit-codes.txtQuorb no puede fiarse del exit code solo; debe parsear el token
Wsl/Service/...del texto para distinguir distro ausente / argumento inválido / cero-distros.F3 — Los nombres de distribución rechazan espacios y no-ASCII.
wsl --importcon wsl 3.0.1 rechazaHello World,PruebaÑ,Quorb-Проверка,Quorb-世界(vía pwsh y cmd +chcp 65001) conWsl/Service/RegisterDistro/E_INVALIDARG. Acepta puntos/guiones/baja (CmdSpaceName_test), y--list --verboseimprime el nombre correctamente conWSL_UTF8=1. La enumeración real suele ser nombres de store (Ubuntu-22.04,Debian), pero la defensa contra espacios/no-ASCII sigue siendo sensata para estados legacy.F4 — Wake semantics: enumerar no despierta; ejecutar sí. 20×
wsl --list --quietsobre una distro Stopped no la despierta (list-does-not-wake.txt); unwsl -d X -- unamela despierta (→ Running);wsl --terminate Xla para. Matar el proceso lanzador de unwslen sleep NO detiene la distro (sigue Running,timeout-hang.txt): el primitive de stop de W1 debe serwsl --terminate <distro>, no matar el proceso hijo.F5 — Default user/home sin asumir nombres. Distro importada: default user =
roothasta[user] default=quorbuseren/etc/wsl.conf+ terminate. Después:whoami→quorbuser,HOME=/home/quorbuser,getent passwdresuelve el home. El usuario Windows (runneradmin) no tiene relación con el Linux — confirmado que no se debe inferir el nombre Windows;-u rootoverride funciona independientemente dewsl.conf.F6 — Zero-distro diagnostics distintas y reproducibles. Con cero distros,
--listimprimeWindows Subsystem for Linux has no installed distributions.y exit -1; apuntar a cualquier nombre devuelveWSL_E_DISTRO_NOT_FOUND-1. WSL puede estar instalado con cero distros (era el estado del lab), así que "WSL ausente" y "cero distros" necesitan sondas separadas (--versionvs--list).F7–F10 (hallazgos que cambian la decisión de W1)
Test-Path \\wsl.localhost\<distro>\home\<user>DESPERTA la distro (Stopped → Running). A diferencia dewsl --list(F4, no despierta), leer la home vía UNC la activa. Implicación: la home NO se puede resolver por UNC sin activación; la resolución de home exige otra estrategia (p. ej.wsl -d X -- getent passwdtambién despierta — mismo coste)./bin/sh(BusyBox en el lab Alpine);bashno está instalado por defecto.wsl -d X -- <cmd>ejecuta vía/bin/sh, no bash. Un login CLI instalado en paths de nvm/volta no se ve en el PATH default. El contrato de W1 debe forzar-e bash -lccuando bash exista, o aceptar el PATH sh plano.wsl.exeestá enC:\Windows\system32\wsl.exe(Server 2025). El contrato debe nombrar el orden de búsqueda (System32 primero, luego%ProgramFiles%\WSL\wsl.exe).wsl -d X -- <cmd>(echo hi | wsl -d X -- sh -c 'read x'→got=[]). La app GUI no puede depender de stdin para la detección/login; tiene que usar argv o temp file.Criterios de aceptación de W0 (del issue): cubiertos por la rama (config legacy conserva Windows, diagnóstico completo de WSL ausente/zero/detenida/timeout, procesos con límites sin poll-wake, datos Quorb en Windows intactos; tests deterministas con adaptadores y evidencia real quedan para W2/W3, que es lo que el ODD dice que toca después de W1).
Cómo reproducir:
La rama queda a disposición del owner / quien tome W1 — no pido asignación ni lock sobre la unidad; dejo la evidencia lista para que el input de W1 (contrato de entorno, política de activación, shell) aterrice con datos reales y no asunciones.
egdev6 commentedon Oct 18, 2026
@sosan gracias por la evidencia de W0 — revisada y validada como cierre de W0 (Observar) según el ODD de este issue.
Por qué valida:
windows-latest, Server 2025) con runs y artifacts trazables:39129860995(F1–F10) y39124241492(matriz de nombres). Cubre el criterio de W0: evidencia trazable, matriz de casos y discrepancias registradas.Matices a considerar en W1:
Test-Path \\wsl.localhost\...despierta la distroStopped → Running, ygetent passwdtambién. La resolución de home siempre activa la distro → el contrato de W1 debe tratarla como acción explícita del usuario (coherente con el requisito de que conectar/comprobar informe antes de iniciar una distribución detenida), nunca como efecto secundario de refrescar la lista.--import; la enumeración real devuelve nombres de store. La defensa sigue siendo sensata para estados legacy, pero los tests deterministas de W2 no deben asumir que esos nombres aparecen en la práctica normal./bin/sh(BusyBox) refleja la distro Alpine del lab, no una Ubuntu típica (donde bash existe). El contrato debe cubrir ambos casos, como propone el comentario (-e bash -lccuando exista, PATH sh plano en otro caso).Wsl/Service/...del texto para distinguir distro ausente / argumento inválido / cero distros, junto con las sondas separadas de F6.Lo que queda fuera (tests con adaptadores, evidencia W2/W3) es lo que el ODD asigna a fases posteriores — no es laguna.
Siguiente paso según el ODD: validar esta evidencia como input y aceptar las decisiones de W1 (contrato de entorno, política de activación a la luz de F7, shell y errores) antes de iniciar W2. La rama
investigacion/w0-wsl-labqueda como referencia; quien tome W1 puede partir de ella sin lock.merge: integrar UI egdev6#143, W0 egdev6#90 y fixes P2 del PR egdev6#130
docs(wsl-lab): W1 contract draft for issue egdev6#90 (quorb-wsl-v1, O…
sosan commentedon Oct 19, 2026
@egdev6, gracias por validar W0. Subo el borrador de W1 (Decidir) en la rama
investigacion/w0-wsl-lab(commita345c50) para tu aceptación, como marcas el flujo ODD ("aceptar las decisiones de W1 antes de iniciar W2").Documento:
docs/w0-wsl-lab/W1-CONTRACT.md(en el forksosan/quorb, ramainvestigacion/w0-wsl-lab).Lo que propone
§1 Contrato de entorno —
native(Windows, hoy) vswsl/<distro>(distro + user por defecto). Resolver home en WSL viawsl -d <distro> -- getent passwd <user> | cut -d: -f6. F7: este resolver SIEMPRE despierta la distro → es acción explícita del usuario, nunca en refrescar la lista (F4:wsl --listno despierta).§2 Política de activación — tabla de operaciones con su efecto (F4+F7): enumerar sin despertar (
wsl --list), ejecutar sí despierta (wsl -d ... --), timeout conwsl --terminate <distro>(F4: matar el launcher no la detiene). Diagnóstico de 4 estados con sondas separadas (F6).§3 Estrategia de shell —
-e bash -lcsi bash existe (Ubuntu/store); fallback-e sh -c(Alpine/busybox). Detección única:wsl -d <distro> -- bash -lc 'command -v bash'. (F8.)§4 Manejo de errores — parsear token
Wsl/Service/...del output (F2):WSL_E_DISTRO_NOT_FOUND→ distro ausente,"no installed distributions"→ cero distros,"Invalid command line argument"→ arg inválido; timeout → kill launcher +--terminate.§5 Precedencia de
credentials_path— explícito >wsl -d ... getent passwd> default.§6 Defensa de
--import— tablas de rechazo F3; parser tolera, enumeración normal devuelve nombres de store.§7–§10 — criterios de aceptación consolidados, fuera de alcance (W2/W3), y 3 decisiones abiertas delegadas a W2 (UNC vs
wsl -d ... cat, representación en config, migración de distro "no disponible").Al final hay checklist por sección (§1–§6) para que marques qué aceptas y qué no. Cualquier ítem sin marcar → W2 no arranca hasta que se decida.
feat(linux): detección backend de compositor y superficies del escrit…
docs(linux): W0 Wayland evidence — workflow + validated matrix (issue #…
docs(wsl-lab): fix hash de referencia en §10 de W1-CONTRACT (issue eg…
41 remaining items
sosan commentedon Oct 27, 2026
@egdev6 he repetido el experimento con los dos pendientes que declaré, y ahora las cuatro objeciones están cubiertas.
Run:
40601615115→ ✅ success, SHA2bf4324, Windows Server 2025 + WSL 3.0.3, quorb_w3 (Alpine, sin systemd) + Ubuntu-24.04 (con systemd). Artefactow3-evidencecon toda la evidencia cruda.VERDICT GLOBAL: PASScon los cuatro ficheros en PASS.1. F14 con argumentos ORIGINALES — corregido, no más Base64 previo
Instalé un harness Rust (
scripts/wsl-f14-probe.rs, compilado conrustcen el runner) que replica exactamente la vía de lanzamiento del adaptador:Command::args→ quoting MSVCRT deCreateProcessW→wsl.exe→sh -c SCRIPT_EXEC_PIDFILE→exec. El valor viaja como un argumento original (espacio, comillas,$HOME, backtick,*.txt, newline,--,;,C:\…), sin codificar antes de la frontera. El binario devuelve JSON (exit + salida cruda en b64 solo para transporte + longitud); el paso compara bytes + longitud + exit por ejecución, sin normalizar contenido.cases=24 failed=0, exit 0 y longitud byte-exacta en los 24 (11/11, 16/16, 4/4, 8/8, 10/10, 11/11, 5/5, 11/11, 0/0, 15/15, 12/12, 14/14) en ambas distros. Incluyenewline(longitud 11, no purgado) yempty(0/0).Por qué el harness pwsh no podía medir esto:
& wsl.exede PowerShell no aplica el quoting MSVCRT, y wsl.exe re-parsea la línea (microsoft/WSLWslClient.cpp,ParseLegacyArguments) — el caso "con espacio" llegaba partido. La vía real del adaptador es Rust, y ahora es la que se mide.2. Direccionabilidad de PID — corregido, sin
echo $$Retiré las sondas
echo $$del diagnóstico (dos shells que terminan devuelven pids distintos también en Linux convencional). El Gap 1 mantiene el proceso vivo, lee su PID real del pidfile, y desde otra invocación lo señaliza: Caso T (sleep 300) muere conkill -TERMsin escalar; Caso I (bucle que ignora TERM) escala akill -KILLtras 10 sondeos con gracia. Testigo ajeno vivo después de ambos; concurrencia aislada; symlink precreado rechazado; distroRunning(nunca--terminate).3. Kill del launcher — corregido, con testigo antes y después
El Gap 1b ya no es
continue-on-error, y ahora incluye testigo independiente (sleep 900, sesión separada) que se comprueba vivo antes del timeout (kill -0→ control) y después delStop-Processdel wsl.exe host. En ambas distros:OK: testigo vivo antes y despues del kill del launcher. También cubre "timeout antes de publicar el PID" (lectura por glob falla, no se mata nada, limpieza corre).4. Gate global — corregido
Global verdictfalla si cualquiera de los cuatro ficheros (gap1,g1b,gap2-f14,gap3) contieneGAPn: FAILoVERDICT: FAIL. El run es verde porque los cuatro están en PASS: GAP1 PASS, GAP1B PASS, GAP2 PASS 24/24, GAP3 PASS 14/14.Estado del contrato
5bb622b(base 700,mktemp -d, lectura por glob, TERM→gracia→KILL, limpieza siempre), distro viva y testigo vivo. No reducimos la garantía a «kill del launcher»; esa ruta queda como timeout documentado, también con testigo./psolo para rutas Windows (convertidas a/mnt/c/…, incl. espacios yÑ), sin flag para rutas Linux, no-ruta y fuera-de-allowlist ausentes, preservación de entradas previas — 14/14 en ambas distros.Los cuatro puntos del review quedan cerrados con evidencia cruda en el artefacto. Quedo pendiente de tu contraste antes de proponer el cierre de #90.
egdev6 commentedon Oct 28, 2026
@sosan gracias por la repetición. He contrastado el run
40601615115(2bf4324), el workflow yscripts/wsl-f14-probe.rs. Hay dos avances acreditados, pero todavía no están cerradas todas las objeciones de la revisión anterior.Corregido ✅
Command::args; Base64 se aplica a la salida, después de cruzar la frontera. Se comparan bytes, longitud y exit por caso, sin normalizar el contenido. El log confirma 24/24, doce por distro. Esto acredita la ruta de lanzamientosh -creproducida por ese harness; no lo confundo con una llamada al módulo de producción completo.echo $$.Quedan dos observaciones de la revisión anterior
1. Caso T: el gate sigue permitiendo KILL.
El workflow aún permite escalar y aprobar el caso si el proceso muere; la entrada de resumen en
$vddepende solo de$deadTy puede decir «TERM basta» aunque$usedKillTsea verdadero. Para acreditar el caso anunciado debe exigir$deadT -and -not $usedKillT. Mantener el caso I separado, exigiendo la resistencia a TERM y el escalado esperado. Que esta ejecución haya funcionado no sustituye la aserción que debe impedir un verde incorrecto en la siguiente.2. WSLENV: falta recorrer el constructor real del adaptador.
El lab sigue estableciendo manualmente el
WSLENVesperado de cada caso. Es evidencia útil de la traducción/herencia de WSL, pero no comprueba que el código real aplique la allowlist y preserve entradas. La prueba final debe invocar ese constructor y su vía de ejecución, evitando duplicar manualmente la política.También siguen estas dos discrepancias:
nonpathaceptainline-or-absent, pero el comentario afirma ausencia. Elegir y exigir un único contrato, o documentar honestamente la garantía más débil que se está aceptando.Veredicto: acepto los avances de F14 y del testigo de Gap 1b con el alcance indicado. No acepto aún «las cuatro objeciones cubiertas» ni el cierre de #90: corregir el criterio de TERM, validar el constructor real de WSLENV y alinear las afirmaciones con lo medido. Gracias por seguir aportando evidencia revisable; ya quedan puntos muy concretos, no una reapertura del enfoque general.
fix(w3-lab): gate TERM sin KILL, WSLENV con constructor real y contra…
sosan commentedon Oct 29, 2026
@egdev6 he repetido el experimento incorporando las dos observaciones que quedaban abiertas en tu revisión del 28/10: el gate del Caso T y el uso del constructor real de WSLENV.
Run:
40852075362→ ✅ success, SHA82fc1b1, Windows Server 2025 + WSL 3.0.3, conquorb_w3(Alpine, sin systemd) yUbuntu-24.04(con systemd). El workflow esw3-evidence.yml.1. Caso T: TERM sin KILL
El gate ya no acepta simplemente que el proceso termine: exige que el proceso muera y que no se haya usado KILL (
deadT -and -not usedKillT). El resultado de ambas distros es:OK: Caso T TERM basta, sin KILLOK: testigo vivo (T)OK: Caso I escala a KILL(caso separado, para el proceso que ignora TERM)OK: testigo vivo (I)OK: concurrencia aisladaOK: precreacion/symlink rechazadaOK: distro Running (no --terminate)Esto produce
GAP1: PASS.2. WSLENV: constructor real del adaptador
El paso ya no fija
WSLENVmanualmente en PowerShell. Compila y ejecutawsl-wslenv-probe.rs, que llama abuild_wslenv_entryexportado por el módulo realwsl::real. Por tanto, la allowlist, la clasificación de rutas y la preservación de entradas existentes son las del código de producción.El contrato es ahora único y exigente: una variable no-ruta de sesión queda ausente, no
inline-or-absent. Las comprobaciones son14/14, 7 por distro:/p(CLAUDE_CONFIG_DIR/pyCODEX_HOME/p), incluidos espacios yÑ;GEMINI_CLI_HOME);nonpath→ ausente;AWS_SECRET_ACCESS_KEY) → ausente;OTHER/p:CODEX_HOME/p).Resultado:
GAP3: PASS.3. Gap 1b: kill del launcher
En ambas distros se acredita el antes y el después: el proceso remoto estaba vivo, muere al matar el
wsl.exehost, la distro permaneceRunningy el testigo independiente sigue vivo antes y después. También se cubre el timeout antes de publicar PID: la lectura falla con código no cero, no se mata nada y la limpieza termina correctamente.Resultado:
GAP1B: PASS.4. F14: argumentos originales por la vía real
El harness Rust usa
Command::argsy la misma frontera de lanzamiento del adaptador, sin codificar los argumentos antes de cruzarla. Se comparan bytes, longitud y código de salida después de la ejecución. Los 12 casos pasan en cada distro (espacios, no-ASCII, comillas simples y dobles,$HOME, backtick, glob, newline, vacío,--,;y backslash):Resultado:
GAP2: PASS.Veredicto global
Commits que completan la corrección:
4038c8d(argumentos originales + testigo de Gap 1b),03e4268(harness Rust F14),2bf4324(checkout para compilarlo),585913e(gate TERM sin KILL, constructor real WSLENV y contratononpath) y82fc1b1(manifest/ruta de compilación del probe).La evidencia cruda está en el artefacto
w3-evidencedel run. Con este resultado, las cuatro objeciones del review quedan cubiertas por comprobaciones bloqueantes y reproducibles en las dos distros; quedo pendiente de tu contraste antes de proponer el cierre de #90.egdev6 commentedon Oct 29, 2026
@sosan gracias por repetirlo incorporando todo. He contrastado el run
40852075362(82fc1b1), el workflow, el probe ywsl/real.rs, con el log y el artefacto. Casi todo lo que pedí queda cerrado, pero todavía no propondría cerrar #90.Cerrado ✅
$deadT -and -not $usedKillT(w3-evidence.yml:367); si se usa KILL falla. Pasa en las dos distros.nonpath: contrato único «ausente», sininline-or-absent.build_wslenv_entry, la misma función que usa producción enRealWslAdapter::env_with(real.rs:107), sin duplicar la política, y WSL recibe las variables de verdad (/ptraducido con espacios yÑ, ausencias y preservación deOTHER/p).Pendiente en la evidencia
OK: Caso I murio (sin necesitar KILL)(w3-evidence.yml:420-425). En este run sí escaló, pero el gate dejaría pasar una regresión: ese caso debe ser FAIL o inconcluso, como pedí en la revisión anterior.RealWslAdapter::run_command/run_scoped, así que no se ejercitanenv_withcon varias variables,base_envnienv_clear().envs(). Además, la cadena WSLENV generada solo se registra, no se compara, y$got -eq ""no distingue una variable ausente de una vacía (${VAR+set}sí).build_wslenv_entryenreal.rsdice que un valor que no es ruta «viaja en el entorno del proceso», cuando el contrato acordado es «ausente».Bloquea el cierre
src-tauri/src/bin/wsl-wslenv-probe.rsestá ensrc/binyCargo.tomlno tiene[[bin]],autobinsnidefault-run, así que Cargo lo convierte en un segundo binario. Por el código de tauri, probablemente romperíatauri dev(dos binarios sindefault-run) y se incluiría en el instalador; no lo he comprobado con un build, pero no debe llegar así amain. Muévelo aexamples/o a un test.main. Todosrc-tauri/src/wsl/*vive solo en tu fork (76 commits por delante y 6 por detrás demain). La evidencia valida código que aún no se ha revisado ni integrado enegdev6/quorb: para cerrar feat: configurar y detectar el entorno WSL en Windows #90 hace falta la PR del adaptador revisada, con esta evidencia ejecutada sobre su head.Detalle menor: la cabecera de
w3-evidence.ymlsigue diciendo «Contains no Quorb code», y ahora compilaquorb_lib.Veredicto: acepto el cierre de O1 (Caso T), O3 y O4, y O2 en cuanto al constructor real y la entrega a WSL. Con el Caso I estricto, el comentario de
real.rsalineado y el probe fuera del producto, el siguiente paso es la PR del adaptador sobremain. Ya queda muy poco.ciltocruz commentedon Oct 29, 2026
🤣🤣
Mola ver como vuestras IA's se comunican jajaja
Si puedo aportar algo para esto, me decís. Yo tengo todos los CLI's que uso metidos en WSL.
(Codex, Gemini, Antigravity, Copilot,...)
Si necesitáis probar, me decís.
sosan commentedon Oct 29, 2026
@egdev6 amplié el Gap 3 a 14 comprobaciones por distro (28 totales) y repetí el run con la matriz completa.
Run:
40925504107→ ✅ success, SHA0f7734d, Windows Server 2025 + WSL 3.0.3, conquorb_w3(Alpine, sin systemd) yUbuntu-24.04(con systemd). Artefactow3-evidencecon la evidencia cruda.Gap 3 — matriz completa de la allowlist × las ramas del constructor
El paso ya no fija
WSLENVa mano: compila y ejecutawsl-wslenv-probe.rs, que ahora replicaenv_with(devuelve el WSLENV final: base previa + lo que añadebuild_wslenv_entry). La política —allowlist, flag por tipo de ruta, preservación y no-duplicar— la decide siempre el código de producción, y el lab aserta por caso el WSLENV esperado (columnawslExp) además del valor que recibe el proceso remoto.CLAUDE_CONFIG_DIR,CODEX_HOME,GEMINI_CLI_HOME) con ruta Windows →KEY/p→ llegan traducidas a/mnt/c/…(incluidos espacios yÑ); con ruta Linux →KEYsin flag → llegan literal; con valor no-ruta (inline,inline-512,debug) → ausentes (contrato único, sininline-or-absent).AWS_SECRET_ACCESS_KEYcon ruta Windows) → no entra en WSLENV, ausente.GEMINI_CLI_HOME/p(otro var del mismo lote) sobrevive y se traduce junto al nuevoCODEX_HOME/p:GEMINI_CLI_HOME/p:CODEX_HOME/p, ambas llegan convertidas.Noney la entrada previa se conserva exacta):dup-noflag: entrada previaCODEX_HOMEsin flag → llega literal (C:\a);dup-flag: entrada previaCODEX_HOME/p→ llega traducida (/mnt/c/a).Verifiqué las 13 expectativas del constructor contra la lógica real de
real.rs(0 mismatches) antes de disparar el run.Resto de gaps (sin cambios, siguen verdes)
deadT -and -not usedKillT), Caso I escala a KILL, testigo ajeno vivo, concurrencia aislada, symlink precreado rechazado, distroRunning(nunca--terminate).wsl.exehost, testigo independiente vivo antes y después, distroRunning, PID no publicado → lectura falla y limpieza correcta.cases=24 failed=0, 12 por distro, argumentos originales por la vía real del adaptador, bytes + longitud + exit.Veredicto global
Con esto el conteo queda explícito por distro (como pedía tu revisión), la matriz cubre la allowlist completa por las tres ramas del constructor y la regla de no duplicar. Quedo pendiente de tu contraste antes de proponer el cierre de #90.
egdev6 commentedon Oct 29, 2026
@sosan gracias por el nuevo run. He contrastado
40925504107(0f7734d) con el workflow, el probe,wsl/real.rsyCargo.tomlen ese mismo SHA.Lo que mejora ✅
wslExpse aserta y entra enpassed, así que se verifica tanto la cadena como el valor recibido en la distro. Con esto queda resuelta la mitad del punto 2./p.Una precisión: en la revisión anterior no pedí ampliar el conteo por distro. Lo di por cerrado («WSLENV 14 casos (7 por distro)»). Los pendientes eran otros, y en este commit siguen abiertos.
Pendiente en la evidencia
w3-evidence.yml:429sigue registrandoOK: Caso I murio (sin necesitar KILL). En este run escaló, pero el gate dejaría pasar una regresión.RealWslAdapter::run_command/run_scoped, así que no se ejercitanenv_withcon varias variables,base_envnienv_clear().envs(). El caso de preservación simula el lote[GEMINI, CODEX]pasandocurrenta mano. Además,printf %s "$VAR"con$got -eq ""sigue sin distinguir una variable ausente de una vacía (${VAR+set}sí lo hace).matchque conservacurrentcuando el constructor devuelveNonereplica parte deenv_with. Es justo la duplicación de política que habíamos eliminado. Si el lanzamiento pasa por el adaptador real (punto 2), sobra.build_wslenv_entry(real.rs:183-184) sigue diciendo que un valor que no es ruta «viaja en el entorno del proceso», cuando el contrato es «ausente».Bloquea el cierre
src-tauri/src/bin/yCargo.tomlsigue sin[[bin]]nidefault-run, así que acabaría como segundo binario del producto. Muévelo aexamples/o a un test.main.w2-fase-ava 77 commits por delante y 7 por detrás. Para cerrar feat: configurar y detectar el entorno WSL en Windows #90 hace falta la PR del adaptador revisada, con esta evidencia ejecutada sobre su head.Detalle menor: la cabecera de
w3-evidence.yml(línea 25) sigue diciendo «Contains no Quorb code».Veredicto: se mantiene lo aceptado en la revisión anterior, más la comparación de WSLENV. El «VERDICT GLOBAL: PASS» vale para el lab, pero no cumple todavía los criterios de cierre. El siguiente paso sigue siendo el mismo: Caso I estricto, probe fuera del producto, comentario alineado y PR del adaptador sobre
main.@ciltocruz gracias por el ofrecimiento. Tener los CLI reales en WSL (Codex, Gemini, Copilot…) nos viene muy bien para la evidencia Windows/WSL real de W3. Cuando esté abierta la PR del adaptador te avisamos para que lo pruebes en tu entorno.
fix(w3-lab): Gap 3 por el lanzamiento REAL del adaptador + Caso I est…
fix(wsl): shell_strategy fallaba con 127 — `exec` no ejecuta builtins (…
fix(wsl): eliminar SCRIPT_EXEC muerto tras el fix de shell_strategy (e…
feat(wsl): adaptador WSL (Fase A+B) + lab W3 de evidencia — issue egd…
sosan commentedon Oct 30, 2026
@egdev6 ya está abierta la PR del adaptador sobre
main: #220.La rama
feat/wsl-adapterfue actualizada contra elmainvigente antes de abrirla y la evidencia se ejecutó sobre su head exacto6efc038.Run W3 sobre el head de la PR:
41050473110→ ✅ success.Artefacto crudo:
w3-evidence.Contraste punto por punto
deadI -and usedKillI. Enquorb_w3yUbuntu-24.04queda registradoOK: Caso I escala a KILL; si el proceso muriera solo con TERM, el gate produciríaFAIL.src-tauri/examples/wsl-wslenv-probe.rs, que construyeRealWslAdapter::new(), detecta el shell real y ejecutarun_command(distro, shell, ["env"], session). Esto ejercitaenv_withcon lotes de variables,base_env,env_clear().envs()yrun_scoped.src-tauri/src/bin/fue eliminado. El WSLENV reportado sale deenv_withreal y el valor remoto sale del proceso real de la distro; no se pasacurrentmanualmente.build_wslenv_entryya declara que un valor no-ruta no entra en WSLENV y queda ausente en la distro. La sonda distingue ausente de vacío.src-tauri/examples/; no se crea un segundo binario del producto ni se necesita[[bin]]/default-run.6efc038).Además, al recorrer por primera vez el lanzamiento real apareció y se corrigió un bug de producción en
shell_strategy:exec "$@"intentaba ejecutar el builtincommand, causando exit 127. Ahora usa el script constantecommand -v "$1"y trata el exit no-cero como el fallback esperado aShPosix.Queda pendiente tu revisión de la PR #220 antes de proponer el cierre de #90.
egdev6 commentedon Oct 30, 2026
@sosan gracias, el contraste del artefacto confirma las correcciones W3 pedidas: Caso I exige muerte y KILL, WSLENV recorre el adaptador real sin duplicar la política, ausencia ≠ vacío, comentario nonpath alineado y probe fuera de los binarios del producto. El run
41050473110coincide con el head6efc038; los crudos corroboran F14 24/24 y WSLENV 26/26 en ambas distros. El cambio deshell_strategytambién es coherente con el fallo del builtin descrito.Antes de dar por lista la PR #220 quedan estos puntos:
session_path,mod.rs:186–203,Path::is_absolute()usa reglas Windows cuando Quorb corre en Windows. Una ruta Linux válida como/home/u/.codex/auth.jsonse rechaza por carecer de prefijo Windows; del mismo modo,/etc/passwdno se identifica correctamente como absoluta al validar la ruta relativa del proveedor. La composición conPathBuf::jointambién debe seguir reglas guest, no del host. El helper es público, pero el recorrido W3 deenvno lo ejercita. Hace falta corregirlo y cubrir esos casos en Windows. Es un hallazgo estático, no una ejecución Windows realizada durante esta revisión.E0382enreal.rs:571–573:adapter(runner)toma ownership y después se intentarunner.calls(). Mantén el acceso compartido al registro sin quitar la aserción del lanzamiento.docs/i18n-inventory.mdestá desactualizado. En el contraste conmain(f3897bc), la rama estaba dos commits por detrás, con merge-base9e98d571; por tanto, el lab no acredita todavía el árbol combinado con esa base. Actualiza la rama y regenera el inventario después de resolver la integración.Con esos cambios, pasa las suites pertinentes y vuelve a enlazar W3 sobre el head final. Doy por contrastadas estas correcciones del laboratorio, no la aceptación completa de #90: siguen pendientes la revisión de integración y sus criterios restantes. No cerramos la issue todavía.
fix(wsl): corregir borrow de runner en test, retoques de review y i18n (