Ver Mensaje Individual
  #1
Antiguo 31 de agosto de 2026, 14:14
Eslopes
Creador de
PowerRustCOBOL
Guru de los Gurus: Por solidos y amplios conocimientos - Issue reason: Por ámplios conocimientos en la materia Concurso: Tercer puesto: Ganador/a del Tercer puesto en un concurso - Issue reason: Juego  Innovación: Por aportar innovaciones - Issue reason: Por aportar soluciones innovadoras 
Última Actividad 27.10.2026 07:38
Posts Posts: 396
Likes enviados Enviados: 31
Likes recibidos Recibidos: 172
Predeterminado Correcciones 1.62.0 a 1.62.129 (desde 1.61.185)
0 Inactivo Inactivo

Lista completa de correcciones desde la 1.61.185 hasta la 1.62.129 (130 versiones de correccion, del 24 al 31 de agosto de 2026). Este ciclo estuvo dedicado por completo a la conformidad con la suite NIST CCVS85 de COBOL-85: al cierre, los 420 programas del alcance compilan (100%) y los 380 programas ejecutables terminan con 8362 aserciones PASS y 0 FAIL en los modulos NC, SQ, IX, RL, IF, IC, ST y SM. A continuacion, cada correccion con su explicacion.

=== PowerRustCOBOL 1.62.0 — 2026-08-24 ===

• La documentación se traduce por regeneración, no por parches

La política anterior exigía que cada cambio de documentación llevara el mismo delta a cinco idiomas en el mismo commit. No sobrevivió al contacto con una Developer's Guide de 319 KB: -pt, -jp y -cn acabaron siendo texto en inglés bajo un nombre de archivo traducido, -es era una traducción parcial estancada en 1.425 líneas frente a las 5.999 del inglés, y -fr nunca llegó a existir. Una traducción que en realidad es inglés es peor que una ausente, porque aparenta estar terminada.

Ahora las traducciones se descartan y se regeneran completas a partir del canónico inglés, y el ciclo se ejecuta solo en un salto de versión mayor o menor — nunca en un fix, donde el coste no se justifica. Cuando un fix toca un documento, sus cinco traducciones se borran y simplemente quedan ausentes hasta que la siguiente versión menor las reconstruye. Ningún archivo en inglés se borra jamás. La política queda registrada en CLAUDE.md (GOLDEN RULE #8) y en specs/steering/docs.md.

- Todo documento en inglés lleva ahora -en. Se renombraron once archivos (observability.md -> observability-en.md, etcétera), de modo que los seis archivos de un documento comparten por fin una única regla de nombres; README.md, los enlaces entre documentos, dos comentarios de documentación en Rust y la skill /docsync se actualizaron con ellos.
- La Ayuda del IDE no necesitó cambios en el resolvedor — docs_embed.rs::split_lang ya aceptaba ambas grafías — pero sus tests afirmaban los nombres antiguos y la vieja realidad de "faltan algunos idiomas". Las aserciones por archivo se sustituyen por every_document_ships_in_every_language, que falla si algún idioma cae de vuelta al inglés: la guardia que habría detectado la guía francesa ausente en su primera ejecución, en lugar de meses después.
- Los documentos de más de 32 KB se parten por entrada del índice en archivos de trabajo temp-*-en.md, se traducen sección a sección, se concatenan de nuevo en orden y los temporales se borran. Los cortes nunca atraviesan un párrafo, una tabla, un bloque de código cercado ni un bloque mermaid. Una ejecución interrumpida se recupera borrando temp-* y empezando de cero — nunca reanudando.
- El umbral de 32 KB no es arbitrario: todas las familias de documentos que quedaron por debajo se tradujeron de verdad, y la única familia por encima es la que se pudrió.

• END-DISPLAY y END-ACCEPT se leían como datos, no como terminadores

Ninguna de las dos palabras existía en el léxer. La tabla de terminadores de ámbito se detenía en el conjunto de COBOL-85 (END-READ ... END-UNSTRING, más END-EXEC y END-TRY), así que END-DISPLAY y END-ACCEPT caían en Token::Identifier — y is_expr_start acepta un identificador. La consecuencia no era un diagnóstico, sino un análisis silenciosamente incorrecto:

Código:
       DISPLAY "A" END-DISPLAY
       DISPLAY "B".
era UN solo display con tres operandos — "A", el terminador y "B" — con la segunda sentencia desaparecida. Un desarrollador que cierra cada verbo explícitamente, el hábito que trae cualquiera que llega de otro compilador, obtenía un programa que ejecutaba e imprimía lo que no era.



Post añadido a las 06:48. Post anterior a las 06:45


Ambas palabras son ahora tokens reales, consumidos por su propia sentencia (p.eat) y añadidos al conjunto de parada del parser compartido de frases de pantalla, de modo que DISPLAY X AT LINE 5 WITH HIGHLIGHT END-DISPLAY termina donde dice terminar, en vez de leer el terminador como un atributo más del display. Siguen siendo opcionales — un punto cierra la sentencia exactamente igual que antes, y un programa que nunca los escribe no se ve afectado. Tests: cuatro en test_statements — el caso de dos sentencias que fallaba, el terminador tras una frase de pantalla, las tres formas de ACCEPT (simple, FROM DATE y posicionada) y una guardia de que ambos verbos siguen analizándose sin terminador. docs/cobol85-supported-syntax.md y la Developer's Guide recogen los dos terminadores.

• El popup de autocompletado estampaba el tipo de cada nombre encima del propio nombre

Se informó contra Neumorphic Light, donde la monoespaciada grande del tema lo hacía ilegible, pero el defecto estaba en el layout y lo arrastraban todos los temas. Cada fila era un selectable_label, que se dimensiona según su rótulo — así que resp.rect.right() era el final del NOMBRE, y la pista de tipo, alineada a la derecha contra ese mismo borde, se pintaba encima del nombre al que anota. La pista de cada fila quedaba por tanto en una x distinta, allí donde terminara su nombre: la señal delatora en la captura del operador es que la pista de Panel 10 está más a la derecha que la de Panel 1.

La fila ahora crece hasta el ancho completo del popup (Button::selectable + min_size). Un átomo de texto plano no crece, así que el ancho extra cae a la derecha y el nombre queda alineado a la izquierda — y el ancla de la pista pasa a ser el borde del popup, que es lo que siempre quiso decir. El espacio vacío a la derecha de un nombre corto forma ahora parte de la fila, de modo que hacer clic en él selecciona ese elemento, como se espera que se comporte una lista de autocompletado.

Confirmado en rojo antes del arreglo, con números: dentro de un popup de 300 pt la fila medía 75.4 pt, el rótulo terminaba en 78.4 y la pista empezaba en 46.3 — 32 puntos de solape. Queda fijado por prompt_ac_row_tests (la fila abarca el popup; rótulo y pista disjuntos tanto a 14 pt como a los 24 pt que fija un tema grande). La fila se movió a prompt_ac_row para que el test ejercite el código real y no una copia.

• "Close AI Assistant" se dibujaba encima del "+" del tamaño de letra

El botón estaba en un sub-layout right_to_left al final de la fila de controles del panel de IA. Ese sub-layout toma el ancho que QUEDA y ancla su contenido al borde derecho — así que en cuanto la fila se quedaba sin sitio, el botón se dibujaba encima de los controles ya presentes, y lo que tapaba era el "+" que agranda la letra del historial. El control no estaba deshabilitado ni oculto por un bug de estado: estaba debajo.

El botón se coloca ahora en el flujo como cualquier otro botón de la fila, y la fila es horizontal_wrapped, de modo que un panel de IA estrecho pasa la cola a una segunda línea en vez de apilar controles unos sobre otros. La fila lleva ocho botones y el panel lo redimensiona el desarrollador, así que tiene que sobrevivir a ser estrecho.

=== PowerRustCOBOL 1.62.1 — 2026-08-24 ===

• Con la barra lateral plegada, los clics caían en el control equivocado

Mostrar un SideMenu plegado en el lienzo del diseñador desliza el contenido hacia la izquierda con el borde del raíl, el mismo deslizamiento que hace Run Form. Ese deslizamiento se aplicaba solo al pintado: hit_top_id seguía comprobando los rectángulos de diseño. El área clicable de cada control de contenido quedaba por tanto un ancho de raíl a la derecha del control realmente en pantalla, así que hacer clic en un control seleccionaba a su vecino izquierdo — en el formulario del informe, hacer clic en la etiqueta verde On seleccionaba CheckBox-2. La única manera de acertar en algo era apuntar a donde estaría con el raíl abierto, que es un lugar donde no se dibuja nada.



Post añadido a las 06:50. Post anterior a las 06:48


Ambas palabras son ahora tokens reales, consumidos por su propia sentencia (p.eat) y añadidos al conjunto de parada del parser compartido de frases de pantalla, de modo que DISPLAY X AT LINE 5 WITH HIGHLIGHT END-DISPLAY termina donde dice terminar, en vez de leer el terminador como un atributo más del display. Siguen siendo opcionales — un punto cierra la sentencia exactamente igual que antes, y un programa que nunca los escribe no se ve afectado. Tests: cuatro en test_statements — el caso de dos sentencias que fallaba, el terminador tras una frase de pantalla, las tres formas de ACCEPT (simple, FROM DATE y posicionada) y una guardia de que ambos verbos siguen analizándose sin terminador. docs/cobol85-supported-syntax.md y la Developer's Guide recogen los dos terminadores.

• El popup de autocompletado estampaba el tipo de cada nombre encima del propio nombre

Se informó contra Neumorphic Light, donde la monoespaciada grande del tema lo hacía ilegible, pero el defecto estaba en el layout y lo arrastraban todos los temas. Cada fila era un selectable_label, que se dimensiona según su rótulo — así que resp.rect.right() era el final del NOMBRE, y la pista de tipo, alineada a la derecha contra ese mismo borde, se pintaba encima del nombre al que anota. La pista de cada fila quedaba por tanto en una x distinta, allí donde terminara su nombre: la señal delatora en la captura del operador es que la pista de Panel 10 está más a la derecha que la de Panel 1.

La fila ahora crece hasta el ancho completo del popup (Button::selectable + min_size). Un átomo de texto plano no crece, así que el ancho extra cae a la derecha y el nombre queda alineado a la izquierda — y el ancla de la pista pasa a ser el borde del popup, que es lo que siempre quiso decir. El espacio vacío a la derecha de un nombre corto forma ahora parte de la fila, de modo que hacer clic en él selecciona ese elemento, como se espera que se comporte una lista de autocompletado.

Confirmado en rojo antes del arreglo, con números: dentro de un popup de 300 pt la fila medía 75.4 pt, el rótulo terminaba en 78.4 y la pista empezaba en 46.3 — 32 puntos de solape. Queda fijado por prompt_ac_row_tests (la fila abarca el popup; rótulo y pista disjuntos tanto a 14 pt como a los 24 pt que fija un tema grande). La fila se movió a prompt_ac_row para que el test ejercite el código real y no una copia.

• "Close AI Assistant" se dibujaba encima del "+" del tamaño de letra

El botón estaba en un sub-layout right_to_left al final de la fila de controles del panel de IA. Ese sub-layout toma el ancho que QUEDA y ancla su contenido al borde derecho — así que en cuanto la fila se quedaba sin sitio, el botón se dibujaba encima de los controles ya presentes, y lo que tapaba era el "+" que agranda la letra del historial. El control no estaba deshabilitado ni oculto por un bug de estado: estaba debajo.

El botón se coloca ahora en el flujo como cualquier otro botón de la fila, y la fila es horizontal_wrapped, de modo que un panel de IA estrecho pasa la cola a una segunda línea en vez de apilar controles unos sobre otros. La fila lleva ocho botones y el panel lo redimensiona el desarrollador, así que tiene que sobrevivir a ser estrecho.

=== PowerRustCOBOL 1.62.1 — 2026-08-24 ===

• Con la barra lateral plegada, los clics caían en el control equivocado

Mostrar un SideMenu plegado en el lienzo del diseñador desliza el contenido hacia la izquierda con el borde del raíl, el mismo deslizamiento que hace Run Form. Ese deslizamiento se aplicaba solo al pintado: hit_top_id seguía comprobando los rectángulos de diseño. El área clicable de cada control de contenido quedaba por tanto un ancho de raíl a la derecha del control realmente en pantalla, así que hacer clic en un control seleccionaba a su vecino izquierdo — en el formulario del informe, hacer clic en la etiqueta verde On seleccionaba CheckBox-2. La única manera de acertar en algo era apuntar a donde estaría con el raíl abierto, que es un lugar donde no se dibuja nada.



Post añadido a las 08:09. Post anterior a las 06:50


La prueba de impacto lee ahora la geometría que el lienzo pintó, de modo que las dos no pueden discrepar por construcción. sidebar::rail_view conserva ids, orden y longitud, así que las consultas de contenedor por índice (orden de render, visibilidad de pestañas, rectángulos de recorte) no se ven afectadas. splitter_division_at recibió el mismo tratamiento: un Splitter es contenido, así que su banda de agarre se desliza con la línea dibujada en pantalla. El diseño sigue sin tocarse jamás — el deslizamiento es una vista, el .cfrm conserva los rectángulos que dio el desarrollador y abrir el raíl los restaura.

Test: a_collapsed_rail_moves_the_clickable_area_with_the _control construye el solape que hizo visible el bug — un control diseñado en x400 pintado en x248, exactamente donde estaba diseñado su vecino — y falla con Some("Left") cuando se retira el arreglo. La Developer's Guide dice ahora que plegar el raíl desliza el contenido también en el lienzo, y que ni el deslizamiento ni el clic cambian el diseño.

=== PowerRustCOBOL 1.62.2 — 2026-08-24 ===

• Un elemento de grupo era una variable propia, no sus elementos subordinados

En COBOL-85 un grupo ES los elementos que tiene debajo, colocados uno tras otro, y es alfanumérico sean ellos lo que sean; su tamaño es la suma de los suyos. Aquí un grupo poseía una ranura de almacenamiento independiente que nada mantenía en sintonía con los hijos, así que los dos se separaban en todas las direcciones a la vez:

Código:
       01 G.
          05 A PIC 99.
          05 B PIC 99.
       …
           MOVE "1234" TO G      *> children stayed 00 / 00
           DISPLAY G             *> "1234" — from G's own slot
           MOVE 11 TO A
           DISPLAY G             *> still "1234" — A is invisible from G
y un grupo cuyos hijos llevaban cláusulas VALUE se mostraba VACÍO, porque nada había escrito nunca la ranura propia del grupo.

Leer un grupo ahora concatena sus elementos subordinados y escribirlo distribuye los bytes entre ellos por anchura — la misma pareja leer-sintetizar / escribir-distribuir que ya tenía 66 RENAMES. La ranura del grupo ya no se consulta para ninguna de las dos operaciones, así que hay una sola fuente de verdad.

• FILLER desaparecía del grupo que lo contenía

ItemSym::children excluye FILLER deliberadamente: es la lista de CORRESPONDING, y un elemento sin nombre no tiene nombre por el que corresponder. Leer un grupo desde esa lista descartaba todos los separadores, así que el clásico registro de hora editada volvía como 23473536 en lugar de 23:47:35_36.

Un grupo lleva ahora una segunda lista, layout_keys — cada elemento subordinado en orden de declaración, FILLER incluido — y los elementos sin nombre reciben una clave de almacenamiento sintética (\u{2}, que no puede aparecer en una palabra COBOL) para que su VALUE se almacene de verdad. CORRESPONDING queda intacto y sigue emparejando solo por nombre. La palabra FILLER sigue siendo opcional, como permite COBOL-85: 05 PIC X VALUE ":".

• La modificación de referencia perdía los ceros iniciales de un elemento numérico

id(start:len) direcciona posiciones de carácter, así que el emisor se toma a su anchura PIC completa. Se estaba representando el valor en su lugar, lo que descarta el relleno: un PIC 9(8) que contenía 00224845 volvía como "224845", y el clásico desempaquetado MOVE T(1:2) TO HH, MOVE T(3:2) TO MM, MOVE T(5:2) TO SS, MOVE T(7:2) TO CC se corría dos posiciones a la izquierda — cada campo tomaba los dígitos de su vecino y el último se caía por el final. Informado mientras se comprobaba un reloj con ACCEPT ... FROM TIME.

Un elemento elemental NO es un grupo solo por llevar condition-names de nivel 88. ItemSym::is_group es !decl.children.is_empty(), y los 88 son hijos ahí — así que 01 WS-GRADE PIC 9(3). 88 PASSING VALUE 60 THRU 100. se leía al principio como la concatenación vacía de cero elementos de datos. Un grupo es ahora el que tiene un layout no vacío.



Post añadido a las 08:12. Post anterior a las 08:09


Tests: tres en test_hierarchy que cubren lectura/escritura de grupos, FILLER (con nombre, sin nombre y anidado) y la anchura de la modificación de referencia; toda la suite de cobolt-runtime está en verde (27 binarios, 224 tests). docs/cobol85-supported-syntax-en.md y la Developer's Guide recogen las tres reglas.

• Editar un documento no reconstruía nada, así que el IDE servía un conjunto obsoleto

docs_embed.rs incrusta el docs/ del repositorio en el binario con include_dir!, que lee el sistema de archivos mientras el crate compila. Cargo no puede ver a través de una macro, así que no tenía motivo para considerar obsoleto el crate cuando cambiaba un documento: editar, añadir, renombrar o traducir cualquier cosa bajo docs/ no reconstruía nada en absoluto, y el visor de Documentación seguía mostrando lo que hubiera quedado incrustado la última vez que algún archivo Rust cambió por casualidad.

Un script de build nombra ahora el directorio (cargo:rerun-if-changed). Medido: una compilación sin cambios termina en 1.2 s, y tocar un solo documento la convierte en 19.6 s — recompila, donde antes no lo hacía. Por esto las traducciones podían llegar al disco y el visor seguir contestando en inglés.

=== PowerRustCOBOL 1.62.3 — 2026-08-24 ===

• Un punto de interrupción puesto después de arrancar la sesión no hacía nada

Los puntos de interrupción eran una instantánea del arranque. El conjunto se leía una vez del margen del editor, se enviaba al depurado al abrirse la sesión y no se volvía a mirar: cada conmutación posterior cambiaba un punto en pantalla y nada más, y el programa pasaba de largo por la línea que el desarrollador acababa de marcar. Cuatro brechas separadas, cada una suficiente por sí sola:
- El margen de la ventana del depurador no era clicable en absoluto — se asignaba con Sense::hover(), así que solo pintaba. El único sitio donde un desarrollador está de verdad leyendo el código mientras está detenido en él era el único sitio donde no podía poner un punto de interrupción.
- RemoteDebugCmd::SetBreakpoints se enviaba desde exactamente un punto de llamada, en el arranque, así que después nada llegaba jamás al hijo rcrun run-form --debug.
- El conjunto compartido del DebugRunner interno del IDE solo se escribía en do_debug().
- DebuggerPanel::set_breakpoints() no tenía llamadores, así que hasta los puntos de la propia ventana y su pestaña Breakpoints quedaban obsoletos.

El margen acepta ahora clics (con un fantasma al pasar el cursor, para que un margen vacío muestre que se puede clicar) y los notifica como DebugAction::ToggleBreakpoint. Un clic se registra contra el archivo que la ventana del depurador está MOSTRANDO — el .cbl generado, que rara vez es la pestaña en primer plano — a través del nuevo EditorPanel::toggle_breakpoint_at. Y sync_breakpoints_to_debuggee corre en cada frame en ambos tipos de sesión, enviando el conjunto siempre que difiera de lo último que se le dijo a ese depurado, de modo que un punto puesto, movido o quitado a mitad de sesión surte efecto en la siguiente sentencia.

Alcanzar un punto de interrupción dentro de un manejador de eventos era el peor caso, y conviene decirlo sin rodeos: el manejador solo corre en la sesión externa rcrun run-form --debug. El DebugRunner interno del IDE arranca el intérprete sin anfitrión de formulario y sin canal de eventos, así que COBOL-WAIT-EVENT toma su rama de CLI, pone COBOL-QUIT de inmediato y el bucle de eventos sale antes de despachar ningún manejador. Depurar el manejador de un formulario significa depurar el formulario, no el .cbl generado desde el editor. Tests: a_breakpoint_can_be_set_on_a_file_that_is_not_in_f ront (la conmutación por ruta que necesita el margen del depurador) y the_window_reports_the_file_its_breakpoints_belong _to (el panel informa de su ruta de origen, set_breakpoints surte efecto y reset limpia la ejecución sin borrar las marcas del desarrollador).

=== PowerRustCOBOL 1.62.4 — 2026-08-24 ===

• "Only my code": el paso a paso cruza el bucle de eventos generado



Post añadido a las 08:14. Post anterior a las 08:12


El .cbl generado de un formulario es en su mayoría fontanería que el desarrollador nunca escribió, y el COBOL-EVENT-LOOP es lo peor de ella: avanzar paso a paso ponía docenas de sentencias entre el desarrollador y su propio manejador. Operador, 2026-08-24: "do not animate the cobol event loop. This is an internal construct... the focus is on the user code."

La funcionalidad entera había sido diseñada de punta a punta y dejada sin su parte central. debugger.rs ya tenía UserScope / DebugUserScope / new_user_scope, el protocolo de cable ya tenía RemoteDebugCmd::SetUserScope { user_only, user_lines }, y codegen::generate_with_user_lines ya informaba de qué líneas generadas contienen los cuerpos de manejadores y procedimientos del propio desarrollador — con un test dorado fijándolo. Pero Interpreter::set_debug_user_scope no existía, debug_check no tenía filtro, form_gui.rs aceptaba el comando como no-op documentado y nada en el IDE lo enviaba jamás. Ninguna de esas cuatro piezas era alcanzable desde otra. Ahora están unidas, y el conmutador está en la barra de herramientas del depurador — ACTIVADO por defecto, puesto que el andamiaje no es código del desarrollador. Ambos tipos de sesión llevan el ámbito, así que se comporta igual venga la sesión de un formulario o del editor.

Los puntos de interrupción deliberadamente NO se filtran. Poner uno es un acto explícito, y negarse en silencio a parar ahí sería una sorpresa peor que atravesar un bucle paso a paso. El ámbito gobierna el paso a paso, nada más. Un ámbito ausente o vacío significa "parar en cualquier sitio" — un conjunto vacío jamás debe leerse como "no parar en ningún sitio", o la sesión parece un cuelgue. Tests: test_debug_scope conduce una sesión de depuración real sentencia a sentencia y compara las líneas en que se detuvo. Con el ámbito activado se detuvo en [10, 12] — las dos líneas de usuario, con 12 líneas generadas cruzadas sin pausa; con él desactivado, [8, 9, 10, 11, 12, 13, 14], cada sentencia como antes.

=== PowerRustCOBOL 1.62.5 — 2026-08-24 ===

• Los registros de fecha y hora daban UTC, no el reloj local

COBOL-85 define ACCEPT ... FROM DATE / TIME / DAY / DAY-OF-WEEK y FUNCTION CURRENT-DATE sobre el reloj LOCAL. Todos se derivaban directamente de SystemTime::now() desde UNIX_EPOCH, que es UTC — una hora del día distinta para la mayor parte del mundo, y una FECHA distinta a ambos lados de la medianoche. Un reloj construido de la manera obvia marcaba tres horas mal en São Paulo: ACCEPT date-time FROM TIME devolvía 00224845 a las 21:22 hora local.

FUNCTION CURRENT-DATE era peor que errónea: era autocontradictoria. Sus últimos cinco caracteres son el desfase respecto a GMT, y devolvía el literal -0000 estuviera donde estuviera la máquina. El único campo cuyo trabajo entero es decir en qué zona está el programa afirmaba GMT, siempre. Los cinco registros leen ahora chrono::Local, y CURRENT-DATE informa del desfase real de la máquina. Medido en la máquina del informe: 23:18:12.76 -0300 contra un reloj de pared que marcaba 231811 -0300, donde antes contestaba 02:18.

Esto no añade nada a la compilación. chrono ya estaba compilado dentro de cobolt-runtime a través de google_maps -> chrono-tz; ahora es dependencia directa del crate que ya lo arrastraba. Ninguna toolchain de C ni biblioteca del sistema llega con la feature clock. Tests: test_local_clock encierra una ejecución real entre dos lecturas de Local::now() — así no puede fallar de forma intermitente en un límite de segundo o de medianoche — y comprueba el desfase informado contra el de la propia máquina. Falla exactamente por el desfase si los registros vuelven alguna vez a UTC, y lo dice en voz alta cuando corre en una máquina que está ella misma en GMT, donde la distinción es invisible.

=== PowerRustCOBOL 1.62.6 — 2026-08-25 ===

• Un IDE instalado no podía compilar, y lo decía en el idioma equivocado
Eslopes is offline   Responder Con Cita