Ir al contenido
English

Plan maestro de cambios — de cero al MVP (hito v0.1)

Directiva 2026-11-01: release-automatica-main automatiza cada push a main con CI verde, sin PR manual de release. Sustituye ese gesto de version-que-propone-ci; firmas, Android y preparación para 1.0 siguen teniendo sus propias changes. La versión se estampa solo en el build.

Backlog ordenado de propuestas de cambio que llevan a Meltemi desde el repositorio vacío hasta el hito v0.1 de Fase 1 (meltemi.md §10). Este documento es el mapa; cada change escribe sus cuatro artefactos (proposal, design, specs, tasks) inmediatamente antes de implementarse — nunca durante, y nunca se implementa nada que no esté aquí o en una change aprobada. Producto de la auditoría de planificación del 2026-07-11 (5 lentes, 64 hallazgos).

Cierre del bootstrap (2026-07-18): la etapa OpenSpec queda cerrada. El motor de specs de fase 1 hospeda la verdad viva del proyecto en .meltemi/specs/ y el histórico en .meltemi/changes/archive/ (migrados con verificación del motor, migracion-openspec-a-meltemi); el método del proyecto son los comandos de Meltemi sobre .meltemi/. El árbol openspec/ se conserva como histórico consultable hasta el retiro físico confirmado por el mantenedor (D3 de la migración).

Desviación aprobada por el mantenedor (2026-07-16, ampliada el mismo día): el backlog está completamente materializado — las 19 changes restantes existen en openspec/changes/ con sus cuatro artefactos (proposal, design, specs EARS, tasks), listas para /opsx:apply en el orden declarado. Disciplina que lo hace sostenible: (1) los deltas de cli-contract son acumulativos — cada uno asume archivadas las changes anteriores del orden; alterar el orden exige revisar esos deltas; (2) los designs de las changes profundas marcan sus decisiones como provisionales y se revalidan obligatoriamente al llegar al frente de la cola (en especial ciclo-sdd-autoria, orquestacion-worktrees y comando-implement, la change de integración); (3) los hallazgos de QA y la deuda registrada están absorbidos en las specs correspondientes (H1/H4/H5 → proxy-permisos; H6 → documentacion-inicial).

Prerequisito Estado
Documento fundacional (meltemi.md v1.0) ✅ Ratificado 2026-07-11
Constitución + rumbo (.meltemi/) ✅ Ratificados 2026-07-11
Change de Fase 0 completa (4 artefactos + enmiendas de auditoría) ✅
Proyección de contexto raíz (AGENTS.md/CLAUDE.md) ✅
Research de integración de agentes persistido ✅ docs/research/integracion-agentes.md
Plan maestro de cambios ✅ Este documento
Ratificación humana (Guillermo) de meltemi.md, constitución y rumbo ✅ 2026-07-11
Registros operativos (org GitHub, org npm, dominio, crates) 🟡 org GitHub y npm hechas (askenaz-dev); meltemi.dev servido por Cloudflare desde el 2026-10-21 (el sitio es de meltemi-web; GitHub Pages de este repositorio, apagado el 2026-10-26); v0.1.0 publicada (2026-07-26, 10 assets firmados); crates por reservar (verificados libres el 2026-07-27)
# Change Alcance Depende de
0 ✅ fase-0-fundacion Constitución ratificada, contrato proto/, esqueleto meltemid, sesión ACP e2e, /propose mínimo —

Ola 1 — método y fundamentos (arranca al cerrar Fase 0):

# Change Alcance Depende de
1 ✅ enmiendas-fundacionales-v1 Vía rápida: ratifica el bootstrap en dos etapas (excepción a §9.3), actualiza §0 a la marca V2, asigna fase a §6.12 (métricas), aclara telemetría post-v1, añade plataforma primaria de desarrollo 0
2 ✅ formato-artefactos-meltemi Esquema canónico de .meltemi/: nombres de artefactos, cabeceras de delta, canon EARS (política bilingüe: estructura en inglés vs prosa en español — resolver la contradicción §5.1/práctica), front-matter de rumbo 0
3 ✅ motor-specs-artefactos Parseo y validación de la estructura .meltemi/ completa (constitución, rumbo, specs, changes, archive) 2
4 ✅ motor-ears-deltas Validación EARS en vivo, parseo/aplicación de deltas; la detección semántica de contradicciones/huecos quedó explícitamente diferida a una change futura 3
4b ✅ enmienda-edicion-movil Vía rápida (2026-07-15): cerca de la edición utilitaria in situ (spec edit-surface) y alcance del compañero móvil monitorear/aprobar/dirigir vía túnel SSH (spec mobile-companion); meltemi.md v1.2 → v1.3 (ratificación pendiente) 1

Ola 2 — superficies (en paralelo con Ola 1 tras el #0):

# Change Alcance Depende de
5 ✅ cli-contrato Gramática de subcomandos, regla de despacho CLI↔TUI, códigos de salida, --json, disciplina stdout/stderr; mapeo comando↔RPC junto a proto/ 0
6 ✅ tui-nucleo-ux Arquitectura de información de la TUI (paneles, navegación), estados vacíos y onboarding de primer uso, accesibilidad terminal (no-solo-color, NO_COLOR, fallback ASCII) 5
7 catalogo-flota Registro público ACP + detección local de binarios; nivel de integración, permisos y estatus por agente 0
8 sesiones-reanudables Reanudar sesión ACP, recuperación tras caída, inspección/navegación de sesiones 0

Ola 3 — capa de agentes completa:

# Change Alcance Depende de
9 proxy-permisos Motor de reglas permitir/preguntar/denegar + UX de la bandeja (cola de peticiones concurrentes, creación de reglas in situ, mitigación de fatiga de aprobación, auditoría) 7
10 niveles-integracion-conformidad Niveles 2 (adaptadores), 3 (headless JSON) y 4 (artefactos); suite de conformidad por nivel con criterios pasa/no-pasa 7
11 proyeccion-contexto Compilación constitución+rumbo+spec activa → AGENTS.md y variantes; bloques gestionados que nunca sobrescriben contenido del usuario 3
12 gestion-contexto-repo Mapa del repositorio, referencias @archivo/@carpeta en prompts 11
13 mcp-passthrough Declaración de servidores MCP e inyección a agentes compatibles; higiene §8.7 7

Ola 4 — el ciclo SDD completo:

# Change Alcance Depende de
14 ciclo-sdd-autoria /constitution, /explore, /propose completo (requirements EARS + design + deltas + tasks con gates humanos), /plan; modo dual spec-full/fast-forward con criterio escrito de proporcionalidad 4, 6
15 revision-specs-ux La obsesión (§4.9): render de diff de deltas en terminal, presentación de contradicciones, checklist interactiva de /review, comentario→instrucción al agente 14
16 orquestacion-worktrees Worktrees aislados, N agentes × M tareas, carreras, merge asistido lado a lado 8
17 checkpoints-rollback Checkpoint automático pre-tarea, reversión granular, alcance honesto (qué NO se revierte) enganchado a la clasificación del proxy 16
18 git-commit-por-tarea Commit atómico con trailer de trazabilidad hasta el requisito EARS; convención de mensajes 16
19 comandos-verify-archive /verify (checklist por requisito + tests vinculados a criterios) y /archive (fusión de deltas en la verdad viva) 4, 18
20 comando-implement /implement: despliegue de agentes sobre tasks.md en modo planificar/actuar con checkpoints 14, 9, 16, 17, 18

Ola 5 — salida al mundo (antes de que el repo sea público / del hito v0.1):

# Change Alcance Depende de
21 gobernanza-comunidad GOVERNANCE.md, CONTRIBUTING.md (contribución vía specs), CODE_OF_CONDUCT.md, SECURITY.md, texto del CLA acotado (§9.3) + tooling de firma, plantillas .github/ — (antes de público)
22 documentacion-inicial README raíz, quickstart, esqueleto de docs/ y tooling de documentación 6
23 distribucion-releases Versionado, firmado y custodia de claves, empaquetado por plataforma, instalador de una línea 6
24 migracion-openspec-a-meltemi El dogfooding definitivo: las specs vivas del propio proyecto migran a .meltemi/ 19
25 hito-v01-aceptacion El escenario del hito como spec ejecutable: una feature de idea a código en terminal con dos agentes de proveedores distintos en paralelo todo lo anterior

Secuencia canónica de las 19 changes restantes (todas con proposal pre-redactada). Satisface el grafo de dependencias y prioriza: completar la capa de agentes con gobierno de permisos, luego el contexto, luego el ciclo SDD, luego el paralelismo, y al final la salida al mundo. Nada queda por fuera.

Orden Change Por qué aquí
1º catalogo-flota Desbloquea #9/#10/#13; sin flota no hay orquesta
2º proxy-permisos Agentes reales exigen gobierno real; corrige H1 (QA) y la deuda del contador de pendientes
3º proyeccion-contexto Cierra la proyección manual de AGENTS.md; vehículo del nivel 4; independiente
4º niveles-integracion-conformidad Cubre el mercado completo (niveles 2/3/4), con la proyección ya disponible
5º mcp-passthrough Los agentes llegan con sus herramientas; capa de agentes completa
6º sesiones-reanudables Robustez e histórico; puerta del paralelismo (#16)
7º gestion-contexto-repo Mapa y @refs para dirigir agentes antes de la autoría pesada
8º ciclo-sdd-autoria El corazón del método — llega con flota, permisos y contexto ya operativos
9º revision-specs-ux La obsesión (§4.9): sin revisión placentera, el método muere
10º orquestacion-worktrees N agentes × M tareas sin pisarse; carreras
11º checkpoints-rollback Autonomía solo con deshacer barato y honesto
12º git-commit-por-tarea Trazabilidad línea→requisito (constitución §8)
13º comandos-verify-archive Cierra los verbos del ciclo; el motor ya demostró la fusión
14º comando-implement La composición de todo (requiere 2º, 8º, 10º, 11º, 12º ya hechas)
15º gobernanza-comunidad Antes de abrir el repositorio al mundo
16º documentacion-inicial El quickstart ya describe un producto real, no una promesa
17º distribucion-releases Empaquetado, firmado, instalador; materializa reserva de crates y alias mel
18º migracion-openspec-a-meltemi El dogfooding definitivo: se retira la herramienta prestada
19º hito-v01-aceptacion El hito como spec ejecutable; la meta de v0.1

Paralelizable sin romper el orden: 15º–16º (documentos, sin código) pueden avanzar en cualquier momento por una sesión aparte; 3º puede adelantarse en paralelo tras 1º. El orden canónico es el de la tabla; toda desviación se anota aquí.

Documentos transversales (se crean durante Fase 1, referenciados por las changes)

Sección titulada «Documentos transversales (se crean durante Fase 1, referenciados por las changes)»
  • docs/plataformas.md — matriz de soporte: SO mínimos, arquitecturas, webviews (antes de #23).
  • docs/presupuestos-rendimiento.md — los números de §12 traducidos a criterios EARS y gates de CI (antes de #6).
  • docs/paridad-nucleo.md — matriz viva capacidad → RPC → TUI → GUI; toda change que añada un RPC la actualiza (desde #5).
  • docs/operaciones/checklist-lanzamiento.md — registros y activos (ver pendientes del arquitecto).

Archivadas el 2026-07-25 (183 escenarios verificados, 64 requisitos revisados uno por uno, deltas plegados a la verdad viva):

Change Qué dejó en la verdad viva
gui-tauri-paridad desktop/ Tauri 2 + Svelte 5, crate compartido core/meltemi-client, matriz de paridad como gate de CI, política de concurrencia humano↔agente (worktree/apply-edit + human_edit + nota al siguiente turno), LSP BYO, instaladores con gate < 15 MB; creó docs/ux/design-system.md y docs/paridad-nucleo.md
gui-clase-mundial Shell de tres zonas con la densidad del design system, identidad de entidades, drawer, superficie de Ajustes, paleta con difusa/grupos/formularios tipados, la sesión como acción primaria, guarda de trabajo sin guardar
flota-deteccion-guia Detección en dos capas (CLI oficial + adaptador) con estado compuesto, remedio por capa con su comando exacto, estatus legal sin maquillaje y docs/agentes.md verificada contra el registro
multiproyecto-suscripciones Registro de proyectos (project/list), agente y suscripción en los metadatos de sesión, árbol Proyecto→Sesiones en la GUI, agrupación y ámbito conmutable en la TUI
analitica-consumo-local analytics/usage: actividad plegada de los registros locales, tokens solo donde la salida oficial los reporta, frontera medido/no-reportado con motivo estable y declaración de honestidad junto a las cifras
sitio-web-producto site/ estático (sin JS, sin orígenes externos), descargas a la última release firmada con nombres estables, tokens derivados del cliente y lint del sitio como gate
tablero-de-carrera Archivada el 2026-08-08. La carrera visible: procedencia por calle en worktree/diff (fuente, suscripción, nivel, sesión, commit y base propia, todo aditivo), el despacho asentando registro de primera clase, el tablero de la GUI (calles lado a lado, acciones con confirmación, merge por archivo) y el del shell (glifo+palabra con gemelos ASCII, despacho sin congelar el bucle); docs/qa/2026-08-07-tablero-de-carrera-smoke.md

Pendientes de Fase 2: motor-propio-byok (propuesta redactada, activa) · lanzador-conversacional (abierta 2026-07-27, implementada y verificada 106/106; no archiva hasta la ratificación de la enmienda) · adaptadores-propios-acp (abierta 2026-07-27, implementada 24/24 con conformidad real anclada; espera la decisión del mantenedor sobre enviar con Codex en nivel 0) · texto-intacto-al-agente (abierta 2026-07-31, vía rápida: el prompt se doble-codifica y el agente recibe acentos rotos; verify limpio, lista para archivar) · avisos-de-escritorio (abierta 2026-07-31, del comparativo de mercado: nada avisa al escritorio cuando un permiso espera) · primer-arranque-del-home (abierta 2026-07-31, vía rápida, del mismo comparativo) · artefactos-de-cada-push (abierta 2026-08-05, vía rápida: el build de cada push a main descargable como artefacto de la ejecución, jamás como release) · vincular-suscripciones (abierta 2026-08-08, planificada: el pedido fundacional — vincular N suscripciones por proveedor desde cualquier superficie, con la variable de contexto como dato del registro) · barra-de-estado-agentica (abierta 2026-08-09, vía rápida candidata: la barra de estado existente aprende a decir el bucle agéntico; primer hallazgo capturado de la auditoría de intuitividad) · harness-global-y-por-agente (abierta 2026-08-09: el harness de agentes — rules/skills/agents/hooks por ámbitos global → por-agente → proyecto, formatos FDH reutilizados, vista efectiva ×3; fase 1 = pilar Rules + vista) · sesion-que-espera (abierta 2026-08-09: el borde del turno aprende a esperar — la sesión vive entre mensajes, como Claude Code/Codex) · pensamiento-a-la-vista (abierta 2026-08-09, vía rápida candidata: destapar el pensamiento que la cadena ya transporta — GUI expandido en vivo, TUI conversacional) · modos-de-autonomia (abierta 2026-08-09: Manual/Semi/Autónomo como posturas por sesión sobre el proxy; Bypass rechazado por §3 de entrada) · modelo-y-esfuerzo-por-sesion (abierta 2026-08-09: modelo y esfuerzo como strings opacos por sesión y por perfil — la palanca de cuotas) · registro-agentes-en-superficie · menu-nativo-aplicacion · sandbox-propio · hooks-eventos · plugins-skills-sdk · i18n-superficies · metricas-sdd-locales · lsp-superficie-revision. (pulido-pre-anuncio, la vía rápida del acabado pre-anuncio, quedó archivada el 2026-07-27.) Las 39 changes abiertas el 2026-09-24 tras el comparativo con Orca tienen su propio orden de abordaje más abajo («Orden de abordaje tras el comparativo con Orca»); su fuente es docs/research/comparativo-orca-2026-09-24.md.

Orden de abordaje de las changes activas — declarado el 2026-08-09

Sección titulada «Orden de abordaje de las changes activas — declarado el 2026-08-09»

Diecisiete changes activas tras tres tandas del mismo día: la conversacional (titulo-de-sesion, piel-de-pestanas, compositor-que-trabaja, redirigir-turno, preguntas-del-agente), la del explore de intuitividad y harness (barra-de-estado-agentica, harness-global-y-por-agente) y la de la revisión del mantenedor con referencias visuales (sesion-que-espera, pensamiento-a-la-vista, modos-de-autonomia, modelo-y-esfuerzo-por-sesion). Criterios, en orden: cerrar el trabajo a medio camino antes de abrir más; dependencias declaradas (preguntas-del-agente exige redirigir-turno; sesion-que-espera toca el mismo borde del turno que redirigir-turno y van adyacentes); el bucle diario del mantenedor antes que las apuestas grandes; y lo bloqueado por eventos externos no gasta turno. Toda desviación se anota aquí.

Orden Change Estado (motor) Por qué aquí
— lanzador-conversacional 52/52, verify 106/106 Espera solo la firma v1.5 (pendiente 1c del arquitecto, gate de archivo); no es trabajo de agente
1º ✅ artefactos-de-cada-push 7/7, verify 9/9 Verificada en runner real con el artefacto descargado y abierto. Espera review
2º ✅ piel-de-pestanas 8/8 verify, smoke hecho «El manejo de tabs está feo»: la anatomía de Chrome. Espera review
3º ✅ titulo-de-sesion 13/13, 11/11 verify, smoke hecho Las pestañas nombran el trabajo, no un hash. Espera review
4º ✅ compositor-que-trabaja 7/7, verify 5/5, smoke hecho El anillo de trabajo y ■ Detener donde se escribe. Espera review, que además ratifica la enmienda del design system
5º 🔸 pensamiento-a-la-vista 3/4, verify 6/6 La misma experiencia que el 4º: la luz dice «trabajo», el transcript lo muestra — destapar el pensamiento ya transportado (GUI) y el pliegue conversacional de la TUI
6º barra-de-estado-agentica proposal El cromo ambiental: proyecto, change+gate, sesiones por estado, tokens con frontera honesta
☆ Auditoría de intuitividad sesión dedicada, no change Tras la tanda visual (2º–6º): barrido CDP sistemático → informe en docs/qa/ + la siguiente tanda; correrla antes re-hallaría lo ya capturado
7º primer-arranque-del-home proposal Vía rápida chica del comparativo: el chip advierte proactivamente; onboarding listo antes de cualquier anuncio
8º avisos-de-escritorio proposal La atención cuando la app no tiene foco; preguntas-del-agente la da por presente en su experiencia
9º redirigir-turno implementada (12/12, verify 9/9) El verbo del medio (interrumpir y relevar, atómico en el daemon); prerrequisito declarado del 11º; paridad ×3 servida en la change
10º sesion-que-espera implementada (verify 19/19) El chat que no muere: el borde del turno espera en vez de cerrar — mismo código que el 9º, adyacentes para no reabrirlo dos veces; la evidencia que eventos-para-tardios dejó pedida
11º preguntas-del-agente proposal La corona del bucle conversacional: AskUserQuestion contestada donde se escribe; depende del 9º y aprovecha el 8º
12º modos-de-autonomia proposal Manual/Semi/Autónomo como posturas por sesión sobre el proxy existente; Bypass rechazado por §3 de entrada
13º modelo-y-esfuerzo-por-sesion implementada (verify 14/14) La palanca de cuotas: modelo y esfuerzo opacos por sesión y por perfil. Hallazgo de cierre: los adaptadores propios no anuncian opciones de sesión porque ningún proveedor pineado enumera modelos, así que la vía en vivo queda cableada, probada con el mock y disponible para cualquier agente ACP que sí anuncie (design D9)
14º ✅ harness-global-y-por-agente implementada (25/25, verify 15/15) La apuesta estratégica: fase 1 (Rules + vista efectiva) con design por delante; spec-full. Espera review
15º motor-propio-byok proposal La mayor de fase 2; entra tras el harness (la directiva más reciente manda) y con su rename terminológico ya hecho
⏳ procedencia-de-release tasks 6/8, verify 6/6 Sus 2 tareas dependen de eventos externos — una corrida real disparada por tag (próxima release) y la clave pública que entrega el mantenedor — se cierra cuando ocurran, sin gastar turno

Estado al 2026-08-16: hechas 1º–4º y 8º–10º (esperan review); la 5ª solo espera su smoke. Cinco changes del orden siguen con proposal y nada más (11º–15º), y la auditoría ☆ no ha corrido.

Lo que 9º y 10º cerraron juntas —adyacentes a propósito, sobre el mismo borde del turno— es el bucle conversacional del daemon: se puede interrumpir un turno y relevarlo, y la sesión ya no muere al terminarlo. El 10º trajo además la evidencia que eventos-para-tardios dejó pedida para desacoplar un RPC que bloquea el turno entero, y la trajo con su prueba: sin el desacople la espera es imposible, porque la petición que posee la sesión nunca respondería.

Paralelizable sin romper el orden: 2º, 4º, 5º y 6º son solo desktop/ui (el 5º suma el render de la TUI) y pueden avanzar mientras 3º toca daemon+proto, commiteando por tarea (aviso de concurrencia del 2026-07-26). La auditoría ☆ corre en sesión aparte con la app viva. Las changes nombradas sin abrir no cuentan aquí: registro-agentes-en-superficie, menu-nativo-aplicacion, sandbox-propio, hooks-eventos, plugins-skills-sdk, i18n-superficies, metricas-sdd-locales, lsp-superficie-revision, harness-skills, harness-hooks, harness-subagentes, ruteo-declarativo-de-perfiles, el .rpm de Fedora/RHEL y la extensión ACP de usage.

Orden de abordaje tras el comparativo con Orca — declarado el 2026-09-24

Sección titulada «Orden de abordaje tras el comparativo con Orca — declarado el 2026-09-24»

Fuente: docs/research/comparativo-orca-2026-09-24.md — 23 agentes verificando siete dimensiones contra el árbol y contra onorca.dev, más una prueba integrada real en Windows con Claude Code 2.1.280, Codex y OpenCode sobre un daemon aislado de main @ 4bc8e9e. Sesenta brechas verificadas se cubren con 39 changes (todas con proposal.md, en .meltemi/changes/; design/specs/tasks just-in-time al llegar al frente de la cola). Ninguna exige enmendar la constitución; dos traen enmiendas de rumbo/§11 con ratificación como gate.

Criterios, en orden: (1) lo que la prueba integrada rompió se arregla antes que cualquier feature; (2) confianza ejecutable antes de anunciar (procedencia cerrada, corrida publicada); (3) el estado vivo antes que cualquier animación de trabajo, porque sin él la animación miente; (4) el remoto se construye de adentro hacia afuera (cliente → máquinas → lectura → aviso → móvil); (5) lo bloqueado por eventos externos —ratificaciones, ollama, clave pública— no gasta turno. Toda desviación se anota aquí.

Consolidación de nombres: el informe nombra changes chicas que aquí se funden por compartir archivos y capability. arranque-solo-en-endpoint-propio

  • tunel-resiliente + acceso-remoto-documentado → acceso-remoto-afinado; estados-de-carga + pulso-de-la-tui + senal-de-vida-del-turno + ventana-hasta-el-primer-frame + vocabulario-de-movimiento → senales-de-vida; canales-de-comunidad + cadencia-y-changelog + quickstart-sin-cargo (+ FAQ y privacidad) → antes-de-anunciar; pestanas-que-vuelven + bandeja-de-avisos + la-sesion-dice-su-rama (+ exportar sesión) → escritorio-que-recuerda; paleta-que-encuentra + buscar-en-las-sesiones + markdown-que-se-lee + previsualizar-binarios → buscar-y-leer; abrir-pr-con + abrir-terminal-aqui (+ enmienda de rumbo) → abrir-con-lo-tuyo; distribucion-gestores-paquetes + avisos-de-version → distribucion-y-actualizacion; perfil-con-entorno se absorbe en guia-modelos-locales porque [[fleet.profile]].env ya existe.

Tanda 1 — confianza ejecutable (≤ 2 semanas)

Sección titulada «Tanda 1 — confianza ejecutable (≤ 2 semanas)»
Orden Change Vía Brechas Por qué aquí Depende de
1º ✅ codex-al-dia completa · implementada (17/17, verify 40/40) AI-1 Codex no arranca con ninguna versión (0.77: modelo de cuenta; 0.156: user agent que el adaptador no lee). Cerrada: re-anclada a 0.156.1 con compuerta estricta verificada, y la corrida real del 2026-09-25 le re-otorgó el nivel 2 —
2º ✅ turno-vacio-es-error completa (el código de salida 15 modifica la taxonomía viva) · implementada (10/10, verify 29/29) AI-11 un turno sin mensajes ni herramientas se reportó como éxito. Cerrada: el daemon mide cada turno y escribe turn_empty salvo que un humano lo detuviera; cinco respuestas llevan emptyTurn; el CLI sale con 15; GUI, TUI y la analítica lo muestran —
3º ✅ aprobador-en-el-cli completa · implementada (7/7, verify 21/21) AI-12 el CLI denegaba todo permiso: con Claude Code solo servía para charlar. Cerrada: en un terminal pregunta con las opciones del agente y lo que envió (completado con la tool_call de la sesión, sin texto crudo del agente); recordar escribe la regla más específica o no se ofrece; sin terminal, el rechazo del agente y un aviso que nombra las reglas; Ctrl+C cancela primero (el log dice interrupted) y sale con 13; el terminal siempre sale del modo crudo —
4º ✅ modelo-por-opcion-anunciada completa · implementada (10/10, verify 27/27) LM-3, LM-6 --model rehusado a un agente que anuncia modelos; el model del perfil se pierde en propose/dispatch/implement. Cerrada: cada palanca va por la bandera que declara su entrada del registro (levers: Codex modelo y esfuerzo, Claude Code modelo) o por la opción que el agente anuncia, fijada y confirmada antes del primer prompt (la última respuesta decide, el modo no se mueve, espera acotada [sessions] lever-wait y cancelable); si no, se rehúsa sin prompt como lever_refused y el 2007 con sus datos, acotados y escapados en las tres superficies; el perfil rige en todo verbo antes de sus efectos (propose ya no deja andamio); el histórico dice lo que rigió y nunca lo rehusado —
5º ✅ usage-desde-acp completa (la revisión adversarial mostró dos MODIFIED: la frontera entre medido y no reportado, y el evento de uso de session-history) · implementada (8/8, verify 16/16) LM-7 usage_update está en el log y usage dice «no reportado». Cerrada: la contabilidad lee el contexto y el costo que el agente reporta por ACP como cifras suyas, aparte de los tokens —por conversación del agente (implement abre una por tarea), una sola vez aunque la conversación se reanude, sumadas por moneda y nunca convertidas—; los tokens de esas sesiones quedan ausentes con el motivo «el protocolo transportó contexto y costo, no consumo»; la CLI y la vista Uso lo muestran rotulado como del agente. Hallazgos corregidos: el plegado perdía binario y nivel de las sesiones con modelo declarado, y una prueba de control remoto corría contra la cancelación previa al primer prompt de la 4º —
6º ✅ guia-modelos-locales rápida · implementada y archivada (5/5, verify 6/6; 2026-10-24) LM-1/2/5/8, P5 la única vía funcional (OpenCode) sin escribir; corrige «Aider funciona hoy». Cerrada: docs/local-models.md con tres recetas (ollama, LiteLLM, OpenRouter) verificadas en forma con OpenCode 1.18.32 el 2026-09-25, cada una con su perfil, y un lint que rehúsa claves en claro; la receta 1 pasó por Meltemi: el perfil llega, --model anunciado se confirma antes del primer prompt y uno no anunciado se rehúsa sin prompt (confirma en vivo la vía anunciada de la 4º); la pierna local queda escrita y pendiente en docs/conformidad-manual.md; Aider deja de prometerse; el README y el LEEME enlazan sin nombrar productos, y el requisito de la página de agentes del sitio pasó a meltemi-web (agents-page-own-model). Hallazgo anotado aparte: un ${VAR} dentro de un texto más largo se resuelve en silencio a vacío ollama en la máquina del mantenedor (pierna local)
7º ✅ verbos-del-agent-boss completa (watch y log son flujos —un registro por línea— y eso es una excepción declarada a las dos reglas de formato: dos MODIFIED) · implementada (10/10, verify 29/29) MOB-5, C-F aprobar, seguir y cancelar por SSH sin TUI; la CLI como herramienta de agentes. Cerrada: seis verbos sobre cinco métodos que ya existían —permissions, approve, deny, watch, log, cancel—, sin RPC nuevo; se decide con lo que el agente ofreció para esa petición (la aprobación de una vez cuando es una sola, su rechazo o cancelar, --option de la clase del verbo) y una petición por vez, nunca en bloque; una petición que ya no espera sale con 12, una sesión desconocida con 11; watch declara su interés antes de mirar y no sobrevive a su sesión (su cierre, o una consulta de vida cada 2 s) ni a su daemon (10); el texto del agente viaja como escapes de JSON; la receta «aprobar desde el teléfono, hoy» sin túnel en docs/acceso-remoto.md, probada con el binario sin TTY. Hallazgo corregido: los tests de espera de config.rs compartían directorio temporal y se lo borraban en paralelo (carrera traída por la 4º). Hallazgos anotados aparte: harness --agent rehusado por la gramática, y una sesión aparcada que se cancela cierra con completed —
8º ✅ acceso-remoto-afinado completa (que un endpoint explícito no arranque un daemon estrecha dos requisitos vigentes: dos MODIFIED) · implementada (7/7, verify 15/15) R3, R9, R4, MOB-6, R-V1 un endpoint caído arranca un daemon equivocado; túnel sin latido; Windows servido sin guía. Cerrada: un cliente arranca el daemon solo en el endpoint propio del usuario o con MELTEMI_START_HERE=1, y cualquier otro que no responde se rehúsa al instante nombrando el túnel —medido: el release de main levantaba un daemon en un endpoint ajeno; el nuevo rehúsa en 34 ms—; el arranque bajo demanda, que nunca tuvo prueba, la tiene con el meltemid real (arranca, se reutiliza, se apaga); el túnel lleva latido y ExitOnForwardFailure, --exec corre exactamente lo impreso y un túnel que muere sale con 10; docs/acceso-remoto.md gana el PC Windows servido, el teléfono de hoy (verbos, TUI por ssh -t, campana) y las esperas con sus valores; docs/plataformas.md deja de contradecir al helper; el smoke declara pendientes, con lo que falta, la GUI/TUI sobre un socket reenviado (un host macOS/Linux) y el tramo sshd de Windows (instalar el servidor) host macOS/Linux y OpenSSH Server en Windows (tramos pendientes del smoke)
9º ✅ corrida-integrada rápida (dos requisitos ADDED) · implementada (6/6, verify 6/6) AI-2, AI-V1, P9 la matriz agente × verbo × superficie con informe fechado; el informe de aceptación v0.1. Cerrada: scripts/smoke-agents.ps1 (y su gemelo .sh) corre aislado por las cinco variables los mismos siete verbos contra cada CLI listo y escribe el informe; corrida contra Claude Code 2.1.280, OpenCode 1.18.32 y Codex 0.156.1 (docs/qa/2026-09-26-corrida-integrada.md); el hito v0.1 con dos proveedores reales, los seis criterios aprobados y cinco desviaciones declaradas (docs/qa/2026-09-26-hito-v01-aceptacion.md, enlazado desde docs/hito-v01.md); Claude Code 2.1.280 verificado en nivel 2 por conformance_real. Hallazgos, cada uno con su change: OpenCode edita sin pedir permiso (el proxy no lo gobierna); una regla por ruta no casa con los adaptadores de nivel 2 (adaptadores-con-rawinput); session/log no encuentra el registro de una sesión de worktree; los worktrees de tarea no se excluyen del git del árbol principal; Codex no se reanuda (codex-reanudar-y-mcp); los adaptadores no reportan uso (extension-acp-usage) ollama para la pierna local; el .sh en macOS/Linux
10º ✅ senales-de-vida completa · implementada (10/10, verify 21/21; aterrizada el 2026-10-24, un mes después de terminarse) VIS-3/4/5/6/7/9 esqueletos, cronómetro, spinner de la TUI, ventana al primer frame, vocabulario de movimiento — (solo cliente)
11º comandos-del-agente rápida D2, AI-7 el / del agente, anunciado y hoy descartado —
12º arrastrar-referencias rápida D3 (texto) soltar archivos como @ruta —
13º antes-de-anunciar rápida P2, P3, P6, P-V1 canales, CHANGELOG (con el formato que lee meltemi-release notes), quickstart sin cargo, FAQ (la página de privacidad es de meltemi-web: change ide-privacy-statements, que es el gate del anuncio, no de los artefactos) gate: release-con-el-push (0.2.0 publicada y verificada con gh attestation verify) cumplido el 2026-10-23: v0.2.0 publicada y verificada con red y sin ella
12º bis ✅ release-con-el-push completa · implementada y archivada (2026-10-24, verify 41/41; la 7.3, apagar Pages, cerrada el 2026-10-26) (enmienda y cierre de procedencia-de-release; REMOVED de «Publicación del sitio con la release» y de product-site en este repositorio) P1, P4 (web) decisión del mantenedor del 2026-10-23: la release nace de un push a main que cambia la versión, sin paso manual; la firma es la atestación del workflow (se retira minisign y la clave que nunca llegó al árbol); el pipeline avisa a meltemi-web al publicar; site/ y el job de Pages se retiran (tarea 7.4 de delivery en meltemi-web). Primera release por este camino: 0.2.0. Va antes de 13º porque es su gate nuevo el push de los 177 commits locales con sus gates verdes; github.tf de meltemi-web adopta el repositorio del IDE
12º ter ✅ grabador-de-avisos-sin-carrera rápida, sin deltas (solo un fixture de test) · implementada (4/4) — el test del aviso de prueba fallaba en el CI de Windows en dos de las tres corridas en que llegó a ejecutarse: dos avisos seguidos corren dos cmd.exe a la vez, y el >> del grabador .cmd no comparte el archivo, así que se perdía una línea. Cerrada: el grabador toma un candado con mkdir y un test determinista vigila el candado; bajo carga, 12 de 480 corridas rojas antes y 0 de 480 después —
12º quater ✅ seguir-y-cancelar-sin-carrera rápida, sin deltas (solo un test) · implementada (4/4) — following_reading_and_cancelling_end_to_end fallaba a ratos en Windows por dos preguntas tempranas: si la sesión cancelada ya había salido del registro, cuando el daemon publica el cierre antes de darla de baja; y si watch ya escuchaba cuando el agente pidió permiso, cuando watch solo emite desde su suscripción. Cerrada: espera acotada de la baja, y primer turno callado, watch suscrito y entonces la instrucción; bajo carga, 14 de 480 corridas rojas antes y 0 de 480 después —

Paralelizable: 10º–12º son solo desktop/ui/tui y avanzan mientras 1º–5º tocan daemon, adaptadores y proto/; 6º, 8º y 13º son documentación y scripts. Lo que 1º–5º cierran es la deuda que la prueba del 2026-09-24 encontró en una tarde.

Nacidas de la revisión de aprobador-en-el-cli (2026-09-25), con propuesta escrita y sin turno en este orden hasta que el mantenedor lo asigne: adaptadores-con-rawinput (los adaptadores propios mandan el comando y la ruta en la petición: el aprobador los muestra y las reglas precisas gobiernan a Claude y a Codex), regla-precisa-en-la-bandeja (la bandeja de la TUI propone hoy la herramienta sola, más amplia que el requisito vivo; la cola gana comando y ruta, y las tres superficies proponen la misma regla) y auditar-reglas-y-procedencia (crear una regla queda en el log, permission/decide dice si no pudo escribirla, y la denegación de un cliente sin terminal deja de parecer la tecla de una persona).

Nacida de modelo-por-opcion-anunciada (2026-09-25), con propuesta escrita y sin turno: selector-de-modelo-que-sabe (recordar lo que cada agente anunció, por agente y perfil, acotado y con escritura atómica, para que el selector lo ofrezca y avise antes de abrir; la revisión adversarial la sacó del alcance porque su clave, sus cotas y su contenido publicado —§9— merecen diseño propio). Desviación declarada al implementar: el contrato de worktree/dispatch llevaba model y effort que el daemon ignoraba en silencio; ahora rigen (design D5). Hallazgo anotado para una change aparte: el mismo dispatch ignora el mode que su schema y el formulario de la GUI ofrecen.

Tanda 2 — estado vivo, transcript rico, remoto usable (1–2 meses)

Sección titulada «Tanda 2 — estado vivo, transcript rico, remoto usable (1–2 meses)»
Orden Change Vía Brechas Por qué aquí Depende de
14º ✅ estado-en-vivo completa VIS-1 session/state a todo cliente; «0 working» con un agente trabajando · implementada (11/11, verify 12/12). Cerrada: la notificación afirma el estado entero de una sesión y no un cambio, así que aplicarla dos veces o en cualquier orden converge — sin números de secuencia, y la foto que una conexión recibe al iniciar puede correr contra la primera transición sin perderla. Canal propio en el hub, sin la regla de delivers: toda conexión iniciada recibe toda transición, porque filtrar por origen era el defecto. El rezago lo ve el daemon, no el cliente, así que el daemon lo repara reenviando la foto entera (el canal de eventos solo lo registra en su log, y por eso sus huecos son mudos). Anuncia el registro, no los doce sitios de llamada. Dos hallazgos del camino: los flujos de un solo turno finalizan quitando la sesión del registro, no marcándola terminada, así que sin anuncio en esa salida un segundo cliente quedaba congelado en «esperando instrucción» para siempre —lo encontró el e2e de dos clientes—; y session/list arma sus filas desde el índice en disco, así que una sesión registrada a mano no aparece en la lista. Medición de la tormenta: 5 clientes × 20 sesiones × 4 transiciones = 400 afirmaciones en 0,32 s sin que nadie se rezague, contra un canal de 1024, así que «sin coalescencia hasta que algo la pida» tiene una cifra detrás. La GUI no tocó ningún componente: los cuatro indicadores derivan de un array y basta mantenerlo vivo. El ticker de la TUI deja de pedir la lista y se queda con los relojes —
15º herramientas-a-la-vista completa D1, VIS-2, AI-4, D9, VIS-8 filas de herramienta con resultado, diff ACP, subagentes, calles vivas 10º, 14º
16º ✅ via-ssh-del-cliente completa MOB-8, R1 el cliente lanza ssh pc meltemi bridge y habla por su stdio; Windows servido por fin · implementada (8/8, verify 9/9). Cerrada: un endpoint exec:<comando> lanza ese comando y habla el protocolo por su stdio, sin shell en medio —un segundo intérprete es una expansión que nadie pidió y la forma en la que se cuelan los huérfanos— y dentro de un ámbito de proceso, así que un cliente que se cierra o muere no deja un ssh vivo. El comando se lee del entorno o de la configuración de usuario y jamás de un repositorio: un endpoint puede nombrar un comando, y un repositorio capaz de fijarlo ejecutaría algo en tu máquina por el hecho de abrirlo. Tres hallazgos del camino: (1) con MELTEMI_START_HERE=1 un endpoint exec: sí habría arrancado un daemon local, agujero cerrado con guarda explícita; (2) el lector del peer descartaba el error del transporte y fallaba con «connection closed» a secas, así que todo el diagnóstico construido para un comando que muere no llegaba al usuario —ahora la razón se propaga, y sirve a cualquier transporte—; (3) el endpoint se quita del entorno del hijo, o un comando que ejecute meltemi marcaría contra sí mismo. Se declaran además las features de tokio que el crate ya usaba por unificación, con lo que cargo build -p meltemi-client a solas compila por primera vez. Lo que Meltemi no hace, escrito: no añade opciones al comando, no gestiona claves ni passphrases, y no da terminal — de donde se sigue que la primera conexión a un host nuevo falla, con su remedio de una vez en un terminal 8º
17º ✅ maquinas-remotas completa (MODIFIED en remote-access) R2, R10, MOB-7, R8 lista de máquinas con nombre, chip, prueba de conexión 16º; identidad-propia para presencia · implementada (7/7, verify 16/16). Cerrada: la lista es [[client.machines]] de ámbito usuario únicamente —un endpoint puede nombrar un comando, así que un repositorio capaz de fijarlo ejecutaría algo en tu máquina por el hecho de abrirlo— y sin material de claves: identity-file, passphrase, port y user rehúsan la máquina entera con el sitio donde ese dato vive, ruidoso a propósito, porque ignorarlo dejaría a alguien creyendo que su clave está en uso sin ver por qué no pasa nada. Cambiar de máquina es reconectar: el endpoint deja de ser constante capturada y pasa a variable del bucle en las dos superficies, con dos sitios que lo atienden —en conexión viva se suelta en vez de drenar, porque lo que está en vuelo es de la máquina que se deja; durante el backoff corta la espera, porque hacer cumplir el castigo de la mala suerte de la anterior es el cliente penalizando al usuario por su propio calendario—. De paso, el terminal gana algo que ya hacía falta: backoff_or_stop descartaba todo comando que llegara durante la espera, así que listar máquinas ahora funciona estando desconectado, que es cuando más se quiere. Probar abre, saluda y cierra, sin pasar por bootstrap: probar no debe poder arrancar nada ni por accidente, y una máquina apagada falla. La presencia se cruza con la malla por nombre y no se inventa cuando no cruza; se lee al abrir la lista y jamás de fondo. Cero RPC y cero cambios en el daemon, que no sabe que existen otras máquinas. Dos hallazgos: la guarda de trabajo sin guardar se hereda como prop desde App en vez de reimplementarse, y reusar la clase CSS machines hizo que el test vivo de identidad-propia —«ninguna fila de máquina de la malla es accionable»— rebanara la lista nueva, que sí tiene botones a propósito: las dos listas no deben compartir selector
18º lectura-por-el-daemon completa R7 editor, búsqueda y ajustes leen el disco del daemon, acotados 16º
19º ✅ aviso-de-espera-opt-in completa MOB-3, R6 el push que la spec permite: comando del usuario, contenido mínimo publicado · implementada (7/7, verify 8/8). Cerrada: [notices] on-waiting de ámbito usuario únicamente, apagado por defecto, ejecutado por el cliente conectado y jamás por el daemon. El contrato del contenido queda publicado en docs/acceso-remoto.md con la change, como §9 exige: cinco variables —clase de espera, sesión, máquina, instante y cuenta— y ninguna ruta, nombre de proyecto ni texto de petición, con la razón escrita (el destino es un servicio que el usuario opera pero no siempre solo). Dos añadidos sobre lo propuesto, con su justificación: la cuenta, sin la cual un aviso no dice si vuelves por una cosa o por siete, y un piso de treinta segundos, porque seis notificaciones seguidas es cómo se aprende a silenciar un canal. Se lanza y se suelta, con tope de diez segundos dentro de un ámbito de proceso, así que un comando que no responde no bloquea la interfaz. El emisor vive fuera del bucle de reconexión en las dos superficies, o un daemon que cae y vuelve reiniciaría el piso. El ensayo ignora el piso y no lo gasta. Hallazgo colateral: tres e2e de e2e_agente_por_sesion fallan de forma intermitente bajo la carga de la suite completa y pasan en aislamiento y en la segunda corrida; no los toca esta change y quedan anotados como fragilidad a investigar 14º; archivar avisos-de-escritorio ✅
20º flota-ampliada rápida AI-3, AI-9 (L1) de 10 a ~18 agentes nivel 1 verificados vendor por vendor 9º (para medirlos)
21º codex-reanudar-y-mcp completa AI-8 Codex reanuda hilos y recibe MCP por el cable 1º
22º mcp-stdio-passthrough rápida AI-V1 stdio es el piso de ACP y hoy se omite —
23º extension-acp-usage completa LM-7, AI-6 tokens de Claude Code y Codex por _meta con espacio de nombres 5º
24º escritorio-que-recuerda rápida C-C, C-D, D13, D-V1 pestañas que vuelven, bandeja con historial, rama por sesión, exportar 14º (avisos)
25º buscar-y-leer completa D7, D5, C-A session/search, paleta unificada, Markdown renderizado, imágenes 18º (imágenes remotas)
26º anotar-el-diff completa D6 comentarios por línea devueltos al agente (meltemi.md §6.8) 15º
27º abrir-con-lo-tuyo completa (enmienda de rumbo) D11, D12 «Abrir PR con…» y «Abrir terminal aquí»; terminal como no-objetivo escrito ratificación del mantenedor
28º demo-animada-del-sitio rápida P4 el producto en movimiento: la captura y los medios en docs/media/; el vídeo en /ide/, su CSS y su lint son de meltemi-web (primero site-figures-provenance) 10º
29º meltemi-doctor rápida P-V1 el diagnóstico que costó una tarde, en una pantalla 1º (rangos de versión)
30º docs-en-el-sitio completa (enmienda §11) P7 la política de idioma decidida y el índice de las docs; servirlas en el sitio es antes una decisión de meltemi-web (la 0006), y el generador es suyo ratificación del mantenedor
31º distribucion-y-actualizacion completa P8, D-V1 winget/brew/scoop tras la release atestada; la actualización la hace el gestor; los repos de destino y la página de descargas son de meltemi-web; el tap (propio o homebrew-tap) lo decide el mantenedor 13º
Orden Change Vía Brechas Por qué aquí Depende de
32º ✅ companero-movil completa MOB-1/2/4/9 Android primero, SSH confinado, canal exec → bridge identidad-propia, 16º, 17º, 14º, 19º, 7º · en curso (6/8 al 2026-10-02). Los cinco prerrequisitos aterrizados. Lo hecho: el canal SSH confinado al crate móvil —en un teléfono no hay ssh del sistema que lanzar, así que lo habla la app— entregado como Box<dyn AsyncRead + AsyncWrite>, que es exactamente lo que el Stream del cliente ya era: ni una línea de meltemi-client cambia; la clave de la app, generada en el teléfono, con la pública para autorizar y la privada cifrada en reposo, y la frontera dicha con precisión porque la frase cómoda es falsa (el almacén de Android no exporta privadas asimétricas, así que firmar por él exigiría JNI y no está hecho); y las cuatro pantallas, con adoptar tras dos puertas —el diálogo de la superficie y el confirm que el daemon exige— y la frontera de autoría contada: el compañero entero tiene un solo campo de texto. Hallazgo que corrigió el design: russh exige uno de ring o aws-lc-rs y trae el segundo por defecto, al contrario de lo que el design afirmó; la prohibición de deny.toml mordió al añadir la dependencia, antes de compilar nada, y quedó una excepción acotada (ring solo como envoltorio de russh) con la prohibición del otro intacta. Cerrada (8/8, verify 7/7): el APK instala y arranca en el emulador y abre en la pantalla «No tunnel», que dice qué falta y que no haya relés ni puertos es deliberado. APK release arm64: 10,69 MB contra el techo de 25 MB declarado antes de compilar, de los que 9,15 MB son la biblioteca nativa. Dos cosas que solo se supieron haciéndolo: el build de Android falla desde el CLI de npm —el proyecto Gradle registra cómo se invocó el CLI y desde un shim registra node, que no puede arrancar; el mensaje nombra el último recurso probado y no la causa—, remediado con el CLI nativo y anotado en mobile/README.md; y env(safe-area-inset-bottom) sola no bastó, la barra de gestos cruzaba dos etiquetas, así que la navegación lleva max(inset, 16px). El orden de tareas se alteró a propósito para descubrir eso antes de escribir más pantallas
33º motor-propio-byok completa LM-4 la cuña BYO-modelo sin depender de OpenCode 6º, 23º
34º adjuntos-en-el-compositor completa D3 (imágenes) bloques de imagen ACP condicionados a la capacidad anunciada 12º, 25º
35º panel-dividido completa D4 dos paneles, sin anidamiento 24º, 10º
36º volver-a-este-turno completa D8 punto de restauración por turno en worktree gestionado 15º
37º segunda-ventana completa C-B una pestaña en el otro monitor 35º, 24º
38º demo-guiada completa P3 meltemi demo con el agente simulado etiquetado 13º, 10º
39º runner-nivel-3 (opcional) completa LM-1, AI-9 solo si Aider u otro CLI headless lo justifica 6º
40º sucesion-y-custodia rápida P10 inventario de claves y segundo custodio procedencia-de-release cerrada

La release que prueba un desarrollador — declarada el 2026-10-28

Sección titulada «La release que prueba un desarrollador — declarada el 2026-10-28»

Fuente: release-para-un-desarrollador (propuesta abierta el 2026-10-28 tras revisar el estado del IDE frente a lo que el sitio declara del cliente de escritorio). No hay spec del escritorio pendiente: lo que hace honesto el «en desarrollo» del sitio son los instaladores sin firma de plataforma, el transcript sin filas de herramienta y el smoke 3.2 de primer-arranque-del-home. La tanda ordena lo ya propuesto para que una persona —el mantenedor, en su máquina— instale desde los assets, trabaje con sus agentes y escriba el informe que acompaña a la release. main @ ee0aa7b: 58 changes activas (28 terminadas sin archivar, 1 con una tarea abierta, 29 solo propuesta), 66 archivadas, 36 specs vivas, 53 commits después de la v0.2.0 sin tocar proto/ ni la gramática del CLI.

Orden Change Vía Por qué aquí Depende de
0º piso-del-aviso-sin-carrera rápida, sin deltas (solo un test) main está en rojo en macOS desde el 2026-10-28: past_the_floor_the_next_wait_is_told_again supone que grabar el primer aviso tarda menos que un piso de 200 ms; el test pasa a medir el tiempo. Una tanda que empieza en rojo no se puede medir —
1º adaptadores-con-rawinput rápida sin rawInput ni locations ninguna regla gobierna a Claude Code ni a Codex y cada petición escala al cliente (86 aprobadas y 32 denegadas a mano en la aceptación del hito); recordar solo funciona con el simulado —
2º archivo-sin-cabeceras-arrastradas rápida split_requirements arrastra la cabecera siguiente del delta; las 28 changes terminadas se archivan con el motor, y el CHANGELOG.md del 3º se genera del archivo —
3º antes-de-anunciar rápida quickstart desde los instaladores, FAQ, plantillas, CHANGELOG.md en el formato que lee meltemi-release notes; su gate se cumplió el 2026-10-24 2º (el archivo es el changelog en bruto)
4º meltemi-doctor rápida la primera pregunta de cualquier problema, en una pantalla; el guion lo usa como primer paso —
5º opencode-que-pregunta rápida OpenCode edita sin pedir permiso: se lanza de modo que pida por ACP o la flota lo declara «no gobernado» con palabras —
6º registro-de-la-sesion-de-calle rápida session/log no encuentra el registro de una sesión de dispatch; los worktrees de tarea no se excluyen del git del árbol principal —
7º primer-arranque-del-home 3.2 tarea abierta el smoke con flota vacía, que espera un fixture sin candidatos alcanzables —
8º release-para-un-desarrollador completa el guion docs/prueba-de-uno.md, el informe en docs/qa/, la regla de docs/release.md y la recomendación de versión (0.3.0); el mantenedor escribe la versión y corre el guion 0º–7º
deseable herramientas-a-la-vista completa el transcript del escritorio deja de pintar píldoras: lo que el sitio llama «pulir la carcasa». Entra si cabe; no bloquea 10º, 14º del orden anterior
si caben regla-precisa-en-la-bandeja, auditar-reglas-y-procedencia completas la bandeja propone la misma regla precisa que el aprobador, y crear una regla queda en el log 1º

Avance del 2026-10-28. 0º y 1º implementados; 2º implementado y, con su motor arreglado, archivadas 27 changes en orden de aterrizaje, cada una con verify completo y un commit propio: barra-de-estado-agentica, compositor-que-trabaja, modos-de-autonomia, pensamiento-a-la-vista, piel-de-pestanas, preguntas-del-agente, redirigir-turno, sesion-que-espera, titulo-de-sesion, harness-global-y-por-agente, sesiones-en-la-barra, apagado-entero-y-modos, codex-al-dia, turno-vacio-es-error, aprobador-en-el-cli, modelo-por-opcion-anunciada, usage-desde-acp, verbos-del-agent-boss, acceso-remoto-afinado, corrida-integrada, estado-en-vivo, via-ssh-del-cliente, aviso-de-espera-opt-in, maquinas-remotas, companero-movil, senales-de-vida, enfasis-con-color y adaptadores-con-rawinput. Antes, dos barridos: ningún requisito lo modificaban dos changes sin archivar, y un MODIFIED (maquinas-remotas sobre remote-access) era anterior a una change ya archivada del mismo requisito, identidad-propia, y se reconcilió devolviéndole la aserción que había perdido. enfasis-con-color y modos-de-autonomia tenían un escenario sin enlazar, y se enlazó. No se archiva lanzador-conversacional (gate de la firma 1c). La verdad viva valida limpia: 37 capabilities (nace agent-harness) y 93 changes en el histórico. Hallazgo de 2º, corregido: el daemon que sirvió los primeros archivos estaba compilado antes del arreglo; la guarda del lote lo detectó en sesion-que-espera (una cabecera arrastrada), se deshizo ese archivo sin commitear, se reinició el daemon y se rehízo. Los anteriores no arrastraron nada porque sus deltas no tenían sección tras un ADDED.

0º piso-del-aviso-sin-carrera, cerrada el 2026-10-28 (2/2, sin deltas): el test del piso pregunta «dentro» antes de esperar al grabador y mide «fuera» desde el último aviso. El CI de la PR de la tanda (run 40779160260, 3946a8e) lo pasó en macOS, donde main estaba en rojo, y en Linux. Se archivó a mano, como grabador-de-avisos-sin-carrera, porque meltemi archive rehúsa una change sin deltas.

3º antes-de-anunciar, cerrada el 2026-10-28 (7/7, verify 6/6): plantillas de error y de pregunta sin issue en blanco, insignias en los dos README, meltemi-release changelog y un CHANGELOG.md que nace con la 0.1.0 y la 0.2.0, la regla y la cadencia en docs/release.md, el quickstart desde los instaladores y docs/faq.md. Encender Discussions queda del mantenedor.

4º meltemi-doctor, cerrada el 2026-10-28 (6/6, verify 6/6): el diagnóstico se compone en meltemi_client::doctor y lo ofrecen el CLI (meltemi doctor, --json, sale con 14 si algo falla), la paleta de la TUI y Ajustes del escritorio, con las mismas frases en español e inglés; nunca arranca un daemon ni ejecuta un agente. La primera corrida real encontró que el adaptador propio de Codex, que viaja en toda instalación, hacía fallar la fila de un agente que nadie instaló; corregido. De paso, la vista de flota de la TUI sin catálogo vuelve a pintar las máquinas, como su comentario prometía.

5º opencode-que-pregunta, cerrada el 2026-10-28 (4/4, verify 3/3): una entrada del registro declara launch-env y el daemon lo aplica en toda resolución de su id —por id, por perfil, como agente del proyecto—, nunca a un agent.command literal, y por debajo de lo que el usuario fijó en su entorno o en su perfil. La entrada de OpenCode lanza con OPENCODE_CONFIG_CONTENT en ask para editar, comandos, red, subagentes y rutas fuera del proyecto; la guía lo dice con el valor, y que OpenCode así mande sus preguntas por ACP es una pierna manual pendiente de docs/conformidad-manual.md.

6º registro-de-la-sesion-de-calle, cerrada el 2026-10-28 (3/3, verify 3/3): el daemon sabe por la forma de la ruta a qué proyecto pertenece una calle (<raíz>/.meltemi/worktrees/<change>/<calle>), y session/log, la búsqueda de una sesión por raíz y la reanudación leen y escriben bajo la clave de ese proyecto; la calle sigue siendo la raíz que el índice guarda. El primer worktree de tarea excluye la raíz gestionada en .git/info/exclude, como ya hacía el taller. El e2e encontró un tercer hueco de la misma historia: un despacho termina sin salir del registro vivo, y session/direct lo rehusaba como «activa pero no dirigible» mientras el daemon viviera; ahora solo rehúsa una sesión que sigue corriendo.

7º primer-arranque-del-home, cerrada el 2026-10-28 (3.2 hecha, verify 3/3): el smoke sobre el binario (Linux, WebKitGTK, dos registros fixture) midió el chip y el saludo, y encontró tres defectos que ya se dieron por buenos en agosto: la flota vacía cambiaba la palabra pero no el tono, la advertencia se leía «sin agentes …», y el lado Rust del estado de la interfaz tiraba fleetGreeted y noticesEnabled en cada guardado —el saludo volvía en cada ventana y apagar los avisos no duraba—. Los tres corregidos y re-medidos, con un test que falla si el host deja caer un campo que la superficie persiste. docs/qa/2026-10-28-primer-arranque-del-home-smoke.md. Nombra pestana-nueva-con-nombre: la miga y la sección «Abiertas» muestran el id interno __new__ de la pestaña del compositor.

pestana-nueva-con-nombre, cerrada el 2026-10-28 (vía rápida, verify 1/1): nombrada por el smoke de 7º y hecha en la misma tanda, porque es lo primero que ve quien abre la app. La miga, el título y la sección «Abiertas» nombran la pestaña del compositor «Nueva sesión», como ya hacía la tira, en vez de mostrar su id interno __new__.

8º release-para-un-desarrollador, lo del agente cerrado el 2026-10-28 (verify 4/4; no se archiva: su gate es la corrida del mantenedor). El guion docs/prueba-de-uno.md —once pasos, de los assets de la release a desinstalar, cada uno con qué haces, qué esperas ver, dónde queda y su desviación conocida, y la plantilla del informe—, atado al binario por la docs CI. meltemi-release changelog --report abre las notas con el enlace al informe y lo conserva al reescribir; la regla y el orden están en docs/release.md. Recomendación de versión: 0.3.0. Lo que queda es del mantenedor (pendiente 8, abajo).

No son gate, y el guion los declara como desviación conocida: codex-reanudar-y-mcp (Codex no se reanuda), extension-acp-usage (Claude Code y Codex no reportan uso), los certificados de firma de plataforma y la pierna local con ollama.

Lo que Meltemi no copia de Orca, y por qué, está en la sección 6 del informe: relé en la nube y push sin túnel (§3), cuentas y uso por API del proveedor (§2/§5), pty sin gobierno, Chromium embebido, GitHub/CI en el daemon, yolo por defecto, telemetría, releases automáticas, JS en el sitio.

Siguen nombradas sin abrir (no cuentan en este orden): registro-agentes-en-superficie, menu-nativo-aplicacion, sandbox-propio, hooks-eventos, plugins-skills-sdk, i18n-superficies, metricas-sdd-locales, lsp-superficie-revision, harness-skills, harness-hooks, harness-subagentes, ruteo-declarativo-de-perfiles y el .rpm de Fedora/RHEL. Nombradas el 2026-10-28 por release-para-un-desarrollador, con su sitio en la tanda de arriba y su propuesta por abrir: piso-del-aviso-sin-carrera, archivo-sin-cabeceras-arrastradas, opencode-que-pregunta y registro-de-la-sesion-de-calle.

La entrega sin huecos — propuestas escritas el 2026-10-29

Sección titulada «La entrega sin huecos — propuestas escritas el 2026-10-29»

Fuente: entrega-sin-huecos (paraguas). Nace de revisar la tabla de estado de /ide/ en meltemi.dev contra el repositorio y la release v0.2.0:

  • el compañero móvil figura como «Not yet» y está construido: la change está archivada y el APK mide 10,69 MB, pero ningún workflow lo compila para Android ni lo publica;
  • el escritorio se publica sin firma de plataforma;
  • el SDK no existe, como dice la tabla;
  • la versión y el CHANGELOG.md los escribe el mantenedor a mano.

El eje es automatizar: que CI proponga la versión en una PR cuyo merge publica, que construya, firme y publique todo lo que el producto tiene, y que el sitio pinte el estado desde la release.

Decisiones del mantenedor (2026-10-29):

  • todo automatizado hasta el merge de la PR de release;
  • la política de firma se enmienda: firmas de plataforma bajo custodia escrita, en jobs que no construyen;
  • un hito probado sube el minor, ya escrito en docs/versionado.md, y la próxima es la 0.3.0;
  • 1.0.0 la propone CI cuando su lista de preparación está en verde; hoy faltan la firma y la prueba de un desarrollador (entrega-sin-huecos D3);
  • una GitHub App, la que el mantenedor ya tiene, para cada token del camino.

Las nueve changes tienen sus cuatro artefactos y validan limpio. Las de meltemi-web están en openspec/changes/ de ese repositorio.

Orden Change Repositorio Vía Por qué aquí Depende de
0º ide-state-as-it-is meltemi-web rápida el sitio dice algo falso hoy —
1º ide-delivery-infra meltemi-web completa los entornos release-pr y signing, la App y los secretos de firma en Terraform la App instalada
2º version-que-propone-ci IDE completa la versión según la política, en una PR de release; el merge publica; el aviso a la web con la App 1º
3º estado-que-publica-la-release IDE completa capabilities.json atestado en cada release —
4º ide-state-from-release meltemi-web completa la tabla del sitio sale de la release, verificada 3º en una release
5º apk-en-la-release IDE completa el APK compilado en CI con su techo de 25 MB; publicado solo firmado —
6º firma-de-plataforma IDE completa la enmienda; MSI, DMG y APK firmados en jobs aislados y verificados contra identidades fijadas 1º, 5º, certificados
7º contrato-publicado IDE rápida los JSON Schemas del contrato como asset de cada release; el índice completo —
8º distribucion-y-actualizacion IDE completa Homebrew, Scoop y winget como canal de actualización 6º para el cask
deseable herramientas-a-la-vista IDE completa (ya propuesta) lo que separa el escritorio de «publicado» —

Del mantenedor:

  • instalar la App en este repositorio (contenido y PRs) y en meltemi-web (Actions), y cargar su id y su clave en el Terraform;
  • el Apple Developer Program, el proveedor de firma de Windows (firma-de-plataforma D4) y la clave del APK, generada y respaldada;
  • la decisión del tap y la salida de winget (distribucion-y-actualizacion D2, D3);
  • confirmar la lectura de 1.0 (entrega-sin-huecos 3.3);
  • correr la prueba de un desarrollador, que es lo que convierte la PR de release en la 0.3.0.

motor-propio-byok — propuesta activa desde el 2026-07-25

Sección titulada «motor-propio-byok — propuesta activa desde el 2026-07-25»

Nace de tres peticiones del mantenedor: una vía para modelos autohospedados (ollama y cualquier endpoint OpenAI-compatible), el manifiesto del motor como concepto de primera clase con un default (el pedido original lo llamaba «harness»; renombrado el 2026-08-09 — la palabra nombra ahora el harness de agentes de harness-global-y-por-agente), y una decisión sobre su proyecto Forge Harnesses. La forma la decidió meltemi.md D6: el motor propio entra a la flota como un agente ACP de nivel 1 (core/meltemi-engine), pilotado por stdio igual que cualquier agente externo — misma detección, mismo proxy de permisos, mismos worktrees y checkpoints, jamás un canal privilegiado. Todo el tráfico de red vive en el subproceso: meltemid no enlaza pila HTTP/TLS alguna, propiedad auditable que sostiene §3.

El manifiesto del motor es un TOML v1 (dialecto, base-url, modelo, prompt, política de herramientas, límites) que el daemon valida y lista, nunca interpreta; el default va embebido apuntando a http://localhost:11434/v1, el único que no privilegia a proveedor comercial alguno. Sin modelo alcanzable rehusa con remedio; nunca degrada en silencio. Las claves BYOK entran solo por referencia ${VAR}, con el lint de higiene existente.

Decisión sobre Forge Harnesses: se mantiene como proyecto separado, conectado por contrato — este repositorio publica el esquema versionado del manifiesto (JSON Schema + fixtures de conformidad) y Forge produce manifiestos que se prueban contra ellos. Absorberlo sometería un laboratorio de iteración de prompts a la constitución entera (spec-first por cada ajuste, clippy en 3 SO, Apache-2.0 + CLA desde el día uno), no compraría ni un test de integración en CI (que por regla no ejecuta agentes reales ni red) y arrastraría a Meltemi hacia el marketplace que su rumbo explícitamente no es. Si alguna vez se absorbe, entra Apache-2.0 bajo CLA, sin excepciones.

Mientras la change no se implemente, correr un modelo local bajo Meltemi ya es posible hoy y sin código nuevo por OpenCode (nivel 1), que habla con endpoints ollama/OpenAI-compatible y con OpenRouter por su propia configuración: las recetas, verificadas y fechadas, están en docs/local-models.md (guia-modelos-locales). Aider (nivel 3) no sirve hoy: el daemon no lanza el nivel 3 —todo verbo lo rehúsa con level_not_pilotable—, y lo hará solo si runner-nivel-3 llega a existir.

El design system del mantenedor vive en design-system/ y es la fuente visual normativa (gui-clase-mundial D11).

instaladores-linux-sin-webview — activa desde el 2026-07-25

Sección titulada «instaladores-linux-sin-webview — activa desde el 2026-07-25»

El gate de tamaño disparó en Linux la primera vez que llegó a apuntar ahí: el AppImage pesa 78 678 520 B contra 15 MB. El número no se ensancha porque no es un número: el design D7 de gui-tauri-paridad dejó escrito que codifica «no empaquetamos motor de navegador», y meltemi.md §7 rechaza esa vía por su nombre. La change retira el AppImage, declara libwebkit2gtk-4.1-0 y libgtk-3-0 en el .deb —que hoy instala limpio y no arranca— y corrige la prosa pública en los dos idiomas. El hueco queda nombrado: fuera de la familia Debian no hay instalador gráfico hasta que exista un .rpm, que es change propia porque exige verificar los nombres de paquete en Fedora/RHEL en vez de adivinarlos.

procedencia-de-release — activa desde el 2026-07-26

Sección titulada «procedencia-de-release — activa desde el 2026-07-26»

Nace de una pregunta del mantenedor tras firmar la v0.1.0 a mano: las empresas grandes no firman desde un portátil. Es cierto — usan HSM/KMS con clave no exportable, o firma keyless sin clave de largo plazo; la ceremonia humana firma claves, no releases. Pero la conclusión no es mover la clave a CI: un secreto de Actions es exactamente el caso que SLSA v1.2 prohíbe en lenguaje normativo, y la firma manual es el único paso que una cuenta de GitHub comprometida no puede completar — un atacante empuja un tag, CI construye y atestigua, y la atestación verifica perfectamente porque registra fielmente su commit.

La change deja la firma donde está y añade lo que falta: una atestación de build sobre el SHA256SUMS publicado, que liga los artefactos al repositorio, al commit y al workflow. Enmienda además el requisito de custodia para que sus promesas sean cumplibles — el ancla de confianza vive en el repositorio y no en la página de release que autentica; el almacenamiento es offline, no hardware-backed (minisign no tiene HSM ni PKCS#11); y «revocar» queda definido como publicar clave nueva y repudiar la vieja, porque minisign carece de mecanismo de revocación.

Deuda declarada al archivar (no se archivó nada fingiendo que estaba hecho): ✅ la captura de escritorio del sitio está publicada y su procedimiento es un script (scripts/capture-desktop.ps1, docs/ux/capturas.md); la firma de MSI/DMG sigue pendiente de infraestructura de certificados; el arranque y la RAM en macOS y Linux se publican en el QA de la primera release que incluya la GUI.

pulido-pre-anuncio — vía rápida, archivada el 2026-07-27

Sección titulada «pulido-pre-anuncio — vía rápida, archivada el 2026-07-27»

Tres defectos de acabado a la vista del anuncio. Uno: siete botones de la GUI apilan el icono sobre la etiqueta — el skin global de botones no declara display y el svg de Icon es block, así que todo botón icono+texto sin regla flex local rompe la línea; la regla global gana inline-flex y las re-declaraciones locales duplicadas se retiran (la repetición por componente era la causa raíz). Dos: «Ver la flota (4)» incrusta el atajo de teclado como falso contador; el atajo ya tiene su afordancia kbd en el sidebar. Tres: los adapter-install del registro recomiendan instalar desde rutas muertas — el codex-acp Rust de Zed quedó archivado el 2026-07-22 y los adaptadores canónicos viven bajo @agentclientprotocol (verificado contra npm el 2026-07-27, no citado de memoria). Deltas ADDED-only sobre gui-shell y fleet-catalog; el refresco del registro es puente honesto mientras adaptadores-propios-acp no aterrice, y el build que acompañe el anuncio se reconstruye tras el merge.

lanzador-conversacional — abierta el 2026-07-27

Sección titulada «lanzador-conversacional — abierta el 2026-07-27»

Nace de la prueba directa del mantenedor: el modal de lanzamiento actual le pareció «ordinario», y el mockup que siguió fijó la dirección final en tres directivas. Supersede y absorbe los borradores sesion-conversacional y gestion-proyectos-en-superficie, que no entran al backlog como changes propias. Uno: home conversacional — compositor al centro con el contexto como chips (proyecto, agente, modo); enviar navega hacia adentro de la sesión, a una vista de conversación con compositor persistente sobre session/direct, burbujas de turno sobre el log de eventos (el log de operador sigue a un conmutador: el transcript es la verdad) y tarjetas de permiso en línea, con estados honestos — «encolada» jamás finge respuesta. Dos: el modo libre es el default — una sesión nueva es una sesión libre gobernada sobre el proyecto elegido; Proponer y Explorar son modos opt-in del mismo compositor. Tres: los proyectos viven en la navegación — sección persistente con sesiones anidadas, «Abrir carpeta…» en el nav y en el chip (diálogo nativo vía el plugin oficial de Tauri, dependencia nueva del cliente justificada §10), acción rápida por proyecto.

El default libre obliga a una honestidad de producto que la propuesta nombra con sus frases exactas: hoy no existe RPC para iniciar una sesión libre (session/direct exige sesión existente; propose/sdd/explore son verbos del método; worktree/dispatch exige change y tarea), y la promesa pública dice lo contrario — «ninguna línea de código se escribe sin una especificación revisada» (rumbo de producto y tesis de meltemi.md). La resolución: la sesión libre queda gobernada siempre (proxy deny-by-default, aislamiento y checkpoints, log apend-only — §3 no se negocia) pero no spec-gated; el método pasa de cerrojo a propuesta de valor por sesión. La redacción de rumbo/product.md y meltemi.md se enmienda con ratificación del mantenedor como gate; la constitución del propio repositorio no se toca — el desarrollo de Meltemi sigue spec-first.

Al daemon entran solo los verbos que la dirección genuinamente no tiene: el arranque de sesión libre (forma final en el design), project/register (alta validada y canonicalizada) y project/forget (baja solo del registro, una línea de olvido en el JSONL que el plegado last-wins resuelve; jamás toca el disco), más el parámetro agent aditivo en el verbo nuevo y en propose/sdd/explore — resuelto por resolve_fleet_agent, con error estructurado que lista candidatos detectados en vez del string crudo. La conversación en sí es composición cliente sobre eventos-para-tardios. Paridad ×3 (§4): verbos CLI, direct interactivo en la TUI (hoy reservado en la paleta), render de proyectos, docs/paridad-nucleo.md al día; el cromo exclusivo de la GUI no tiene deber de paridad, toda capacidad nueva del daemon sí. Fuera de alcance: menu-nativo-aplicacion y registro-agentes-en-superficie siguen siendo changes propias (registrar agentes ≠ seleccionarlos), y el render conversacional del histórico archivado más allá del conmutador de log queda para futuro con evidencia.

Desenlace (2026-07-31) — implementada y verificada; el archivo espera una firma. Los nueve bloques de tareas están cerrados, meltemi validate sale limpio y meltemi verify da 106/106 escenarios, sin una sola marca manual. Lo que quedó decidido y conviene leer aquí, porque son las cosas que la propuesta dejó abiertas:

  • Nombres finales de los verbos CLI (design D9): meltemi session <instruction> [project-root] [--agent <id|perfil>] —no start, que se leería como arrancar el daemon junto a stop— y meltemi projects register|forget <path>, colgados del listado en plural porque project ya toma una raíz posicional y habría leído register como una ruta. --agent se parsea una sola vez en plan y se entrega al subcomando, de modo que vale en cualquier posición; un subcomando que no arranca sesión la rehúsa con diagnóstico en vez de tragársela.
  • El guardián de reversión, que entró en esta change y no en una futura (design D2): checkpoint/revert rehúsa todo punto de restauración cuyo árbol no sea un worktree gestionado, con el remedio de git restore --source. Escribir el checkpoint de la sesión libre sin ese guardián habría armado un verbo existente contra el árbol del usuario —reset --hard más clean -fd sobre trabajo humano sin commitear—; ninguna superficie ofrece ya ese control.
  • La enmienda de la promesa está aplicada y sin ratificar: rumbo/product.md y la tesis de meltemi.md (v1.5) llevan el texto de D5 con su nota de pendiente. Sin la firma del mantenedor esta change no archiva — pendiente 1c del arquitecto, donde además está lo que hay que hacer al firmar.
  • Una enmienda de spec en marcha (design D12): la vista de aterrizaje de gui-shell era «Sesiones» en la verdad viva y estaba fijada por un test; se enmendó el requisito, no la implementación, porque el compositor como llegada es la directiva entera de la change.
  • Documentación: docs/sesion-libre.md (qué gobierna una sesión sin spec, dónde opera, y por qué el punto de restauración no es una reversión ofrecida) y el smoke visual con 21 medidas en docs/qa/2026-07-31-lanzador-conversacional-smoke.md.

Lo que el smoke encontró y esta change no arregla (rumbo de estructura: lo que surge se anota, no se cuela). Dos merecen decisión antes de archivar:

  1. El texto no ASCII llega corrupto al agente — out.push(bytes[i] as char) en core/meltemid/src/repo_map.rs:120 convierte cada byte UTF-8 en un code point Latin-1, así que «acción» viaja como «acción» en todo prompt que pasa por la expansión de @. Es anterior a esta change y de gravedad alta: el agente recibe la frase rota, no solo la pantalla. Anotado arriba como texto-intacto-al-agente.
  2. Olvidar un proyecto con sesiones no quita su nodo del árbol: el daemon lo saca del listado, pero el cliente lo reconstruye como nodo inferido (desktop/ui/src/lib/tree.ts:81) y no distingue los inferidos. Esconderlo dejaría sesiones sin casa en el árbol, que es justo lo que el nodo inferido evita: es decisión de producto, no un arreglo obvio.

Los otros tres (posición en la cola tapada por el aviso de permiso, cierre de turno como línea neutra tras una tarjeta, y el primer fleet/list saliendo antes de que el ámbito de proyecto se resuelva) están descritos con su evidencia en el informe de QA.

adaptadores-propios-acp — abierta el 2026-07-27 (directiva del mantenedor)

Sección titulada «adaptadores-propios-acp — abierta el 2026-07-27 (directiva del mantenedor)»

Dos adaptadores ACP propios, en Rust y en este monorepo, para los dos agentes cuyo nivel 2 depende hoy de adaptadores de terceros: Claude Code y Codex. Esta change revierte una decisión registrada — niveles-integracion-conformidad dejó fuera de alcance «Mantener adaptadores propios: se consumen adaptadores abiertos existentes» — y la reversión se argumenta, no se esconde. El suelo se movió: Zed archivó su codex-acp en Rust el 2026-07-22 y los adaptadores canónicos viven ahora en TypeScript bajo la org agentclientprotocol — la opción Rust upstream murió, y las dos filas adapter-install del registro ya apuntan a rutas rancias. La zona gris del adaptador de Claude basado en Agent SDK es permanente: los términos de Anthropic (feb-2026) nombran al SDK como no autorizado para OAuth de suscripción, y ningún fork lo arregla porque la zona gris vive en la superficie de auth, no en quién mantiene el adaptador. Y los adaptadores propios pueden viajar bundled = true en los instaladores — reutilizando la detección de directorio hermano de motor-propio-byok — matando el muro de onboarding «adaptador no detectado» que flota-deteccion-guia diagnosticó.

El adaptador de Claude pilota el binario oficial claude con la sesión que el usuario ya inició, vía -p --input-format stream-json --output-format stream-json — jamás el Agent SDK, jamás --bare; el flip anunciado de --bare como default de -p queda pineado como riesgo en el design, no se descubre después. Los permisos pasan por --permission-prompt-tool (un shim MCP por stdio que releva al socket existente de meltemid; el daemon no gana transporte alguno) con hooks PreToolUse como compuerta dura, y las pérdidas se declaran: AskUserQuestion se auto-deniega en modo no interactivo y el contrato del prompt-tool está infradocumentado upstream (issue #1175). El adaptador de Codex lanza el CLI oficial codex en modo app-server — JSON-RPC NDJSON por stdio, documentado, la misma interfaz que usa la extensión VS Code del propio proveedor, con esquema por versión vía generate-json-schema que es historia de conformidad lista — y no el patrón de embeber codex-core como librería de los adaptadores Rust archivados, que choca con §2 aunque sea limpio de licencia.

Honestidad legal sin maquillaje: esto no vuelve «sancionado» a Claude — gris pasa a tolerado-con-nota en el mejor caso, y la nota del registro se mantiene veraz; Codex sigue tolerado y mejora, porque desaparece la dependencia de supply chain sobre un proyecto archivado. Anclas: §2 (binarios oficiales, auth gestionada por el agente — el adaptador jamás toca tokens), §5 (los adaptadores entran a la flota como cualquier otra entrada), §6 (prueba por escrito: ACP es el estándar del lado Meltemi; del lado proveedor no hay estándar — stream-json y app-server son la superficie programática oficial de cada uno), §10 (dependencias confinadas a los crates adaptadores) y un solo lenguaje de sistemas. Fuera de alcance: forkear los adaptadores TS y toda vía basada en SDK. Por directiva del mantenedor (2026-07-27: «no quiero ACP de terceros… construimos los propios»), los adaptadores propios pasan a ser la capa por defecto del registro, empaquetados bundled en los instaladores; los de terceros siguen alcanzables por configuración del usuario, pero dejan de ser la vía recomendada.

texto-intacto-al-agente — abierta el 2026-07-31, vía rápida

Sección titulada «texto-intacto-al-agente — abierta el 2026-07-31, vía rápida»

El primero de los cinco hallazgos del smoke conducido del 2026-07-31, y el único de gravedad alta: el prompt llega al agente con los acentos rotos. out.push(bytes[i] as char) en expand_refs (core/meltemid/src/repo_map.rs) recorre el prompt como bytes y convierte cada byte UTF-8 en su code point Latin-1 homónimo, así que «acción íntegra ñandú» entra con 20 caracteres y el registro de la sesión guarda 24. No es un defecto de pintado: lo corrompido es el prompt, y alcanza a todo camino de prompt del daemon —free_session.rs y propose.rs pasan ambos por la misma función—, lo que en un proyecto que se escribe en español significa casi toda frase enviada. Es anterior a lanzador-conversacional; esa change solo lo hizo visible, porque el compositor volvió al usuario lector de su propia frase.

La corrección copia el tramo literal entre referencias como una sola rebanada &str en vez de empujar byte a byte, conservando los índices de byte que la lógica del token necesita para rebanar (design D1). De la misma raíz cuelga el defecto hermano que la change arregla en el mismo aliento: is_ref_char solo admitía is_ascii_alphanumeric, así que un archivo acentuado —ordinario en esta máquina— no se podía referenciar y @informé.md diagnosticaba «no encontrado» sobre un informe que el usuario nunca escribió; el token pasa a char con is_alphanumeric, que admite cualquier alfabeto y sigue dejando que la puntuación española («¿», «—», «…») lo cierre en vez de tragársela (design D2). Deltas ADDED-only sobre repo-context: dos requisitos que escriben lo que hasta hoy era conducta accidental — el texto no referenciado viaja intacto (con @@ literal, que tampoco estaba en la verdad viva) y las rutas fuera de ASCII se referencian como cualquier otra. Cero dependencias nuevas y ningún movimiento del contrato proto/. El barrido de as char se hizo y queda escrito (design D5): un único sitio en código propio, el que esta change arregla.

tablero-de-carrera — abierta el 2026-07-31

Sección titulada «tablero-de-carrera — abierta el 2026-07-31»

Nace de la demostración de aceptación: el daemon corre la carrera multiproveedor entera — worktrees aislados, despacho con el binario y la suscripción de cada proveedor, procedencia persistida, commit trazable — pero ninguna superficie la muestra como carrera, y para verla hubo que construir un tablero externo desechable. El inventario honesto: la GUI tiene medio tablero por accidente (el drill-in de revisión compara diffs de competidores, sin procedencia ni estado ni acciones), el shell anuncia los diez verbos de carrera como «(reservado)» y no renderiza ninguno, y debajo hay tres huecos de contrato que ninguna superficie puede rodear: el despacho no nombra la sesión que abre, el diff por calle calla la procedencia que el daemon conoce, y las sesiones de despacho ni siquiera asientan registro en el índice (aparecen reconstruidas, con nivel mentiroso). La change ensancha el contrato con campos aditivos por calle (cero ruptura, sin verbo nuevo, la matriz de paridad no cambia de filas), hace que el despacho asiente registro de primera clase, y abre las dos superficies: en la GUI el drill-in de revisión evoluciona a tablero (calles lado a lado con procedencia, acciones con confirmación explícita, actualización al concluir turnos); en el TUI el verbo race deja de estar reservado y abre el tablero sin tocar el contrato de dígitos 1–4. Cuatro deltas ADDED-only (worktree-orchestration, session-history, gui-shell, tui-shell), doce escenarios, cero dependencias nuevas; spec-full deliberado — es superficie nueva sobre la feature fundacional, no un ajuste. Fuera de alcance, por escrito: canal push de worktrees (sigue diferido en eventos-para-tardios), merge automático o ranking, y toda vista numerada nueva.

Desenlace (archivada el 2026-08-08). Quince tareas, veintiséis commits, verify 12/12 enlazado sin una sola marca manual, suite en 858. El design salió enmendado por la implementación en un punto que importa: daba por hecho que level, agent_id y profile bastaban para que una calle declarara su resolución, y no bastan — un id de catálogo y un agente configurado que nombra un id se ven idénticos en esos campos, así que deducir la fuente habría sido inventarla; SessionRecord ganó un source opcional que escriben todos los caminos que ya resolvían por la flota. Dos decisiones de implementación que el design no anticipó y quedaron escritas: committed es un hecho del árbol (la cabeza difiere de su base) y no una marca que deje el despacho, de modo que una calle comiteada a mano cuenta; y cada calle conserva su base, porque dos calles de una tarea solo la comparten cuando nadie replicó la asignación contra un HEAD movido. El smoke conducido sobre el binario de release (docs/qa/2026-08-07-tablero-de-carrera-smoke.md) encontró y corrigió un defecto que ningún test de cableado podía ver —la nota de vida partía a mitad de frase pegada al sha y se leía como una oración sobre la base— y dejó anotado un falso positivo del operador que se repetirá si no se nombra: medir una superficie nueva con un binario de target/release viejo se parece exactamente a un bug de la superficie nueva.

vincular-suscripciones — abierta el 2026-08-08

Sección titulada «vincular-suscripciones — abierta el 2026-08-08»

El pedido fundacional en palabras del mantenedor: «si tengo dos suscripciones de Claude y tres de Codex, debo poder vincular esas suscripciones en la flota». El motor existe y está probado (flota-multiproveedor: perfiles con overlay de contexto, resolución sin degradar, carrera de dos suscripciones verificada e2e; el overlay llega al CLI real a través de los adaptadores propios, que lanzan sin limpiar el entorno), y la verificación empírica del 2026-08-08 sobre la máquina de desarrollo lo cerró: CODEX_HOME=<dir vacío> codex login status responde «Not logged in» mientras el contexto por defecto responde «Logged in using ChatGPT». Lo que no existe es el vínculo como experiencia: ninguna superficie crea, deshace ni compone una suscripción — solo TOML a mano, sabiendo por cuenta propia qué variable redirige cada proveedor. La change: la variable de contexto y el gesto de login como datos del registro (jamás un match por proveedor en el código), subscription/link/unlink con persistencia en un archivo propiedad del daemon cargado antes que lo manual (lo escrito a mano gana), el login compuesto y jamás ejecutado (§2: el contexto se crea vacío, no se lee, no se borra al desvincular), el duplicado de contexto advertido, y las tres superficies (§4). Cuatro deltas ADDED-only (fleet-catalog, cli-contract, gui-shell, tui-shell), diecinueve escenarios, cero dependencias nuevas. Fuera de alcance por escrito: ejecutar o verificar logins, balanceo entre suscripciones, y migrar los perfiles manuales existentes.

avisos-de-escritorio — abierta el 2026-07-31 (comparativo de mercado)

Sección titulada «avisos-de-escritorio — abierta el 2026-07-31 (comparativo de mercado)»

Nace del comparativo conducido por el mantenedor contra Orca (Stably AI, 13 capturas) y de una verificación en código que lo confirmó: espera-humana enseñó al daemon a esperar al humano, sesion-esperando y eventos-para-tardios hicieron la espera visible y suscribible — y ninguna superficie avisa al escritorio; los únicos «notification» del cliente son mensajes JSON-RPC del bridge, y la TUI no tiene campana. Un permiso puede esperar minutos con la app detrás de otra ventana, con el turno detenido en silencio. La change: capability nueva attention-notices — aviso local del SO desde los clientes (permiso esperando, gate esperando, sesión terminada o fallida), con regla de foco (al frente, la bandeja de hoy; sin foco, el aviso), contenido sin texto del turno, permiso del SO pedido en el primer aviso real y estado denegado con remedio; GUI vía el plugin oficial de notificaciones de Tauri (el precedente §10 del plugin de diálogo) con «probar aviso» en Ajustes; TUI con campana/OSC opt-in. El daemon no gana transporte alguno: los eventos ya existen, esto es el último metro — y el aviso remoto autohospedado sigue siendo fase 3, jamás del daemon.

primer-arranque-del-home — abierta el 2026-07-31, vía rápida

Sección titulada «primer-arranque-del-home — abierta el 2026-07-31, vía rápida»

El residuo chico del mismo comparativo, verificado en Home.svelte: el rehúso de agente ya guía ejemplarmente (candidatos con estado y remedio dentro del chip), pero solo después de fallar; la cara del chip dice «agente del proyecto» en tono neutro aunque no haya un solo lanzable — el chip de proyecto, al lado, sí advierte cuando falta la carpeta — y la pista del menú vacío nombra la Flota sin abrirla. Deltas ADDED-only sobre gui-shell: el chip advierte proactivamente, el menú vacío gana el gesto a la vista de flota, y la primera llegada con flota poblada muestra «N detectados» una sola vez. El wizard modal y la checklist persistente del comparativo se rechazan por escrito: el compositor con chips es el asistente, en su sitio.

Hallazgos del comparativo anotados, no colados (rumbo de estructura): setup scripts al crear worktrees → su casa es hooks-eventos cuando llegue; issues de GitHub/Jira/Linear como tareas vía CLIs oficiales (gh/glab con su propia auth, patrón compatible con §2) → funciones de equipo, fase 3; automations recurrentes e importar una carpeta con N repos como grupo → futuro con evidencia; y para el anuncio, un contraste que es mensaje y no change: ese producto embarca «Yolo / Dangerously skip permissions» marcado por defecto — exactamente lo que el deny-by-default constitucional de Meltemi existe para no ser.

artefactos-de-cada-push — abierta el 2026-08-05, vía rápida

Sección titulada «artefactos-de-cada-push — abierta el 2026-08-05, vía rápida»

Nace de una petición del mantenedor: «me gustaría que esto sea automático con cada push (para eso tenemos CICD)» — quiere probar el build del día, y en particular el DMG de macOS que su máquina Windows no construye. Lo que no puede automatizarse es la release firmada: procedencia-de-release fijó que la firma minisign ocurre fuera de CI porque es el único paso que una cuenta de GitHub comprometida no puede completar, y con immutable releases activado firmar precede a publicar sin orden alternativo. La change da el escalón intermedio: .github/workflows/build.yml, un job por plataforma en cada push a main, que produce los mismos artefactos que el camino de tag y los sube como artefactos de la ejecución — sin release, sin versión, sin firma y sin insinuar ninguna de las tres. release.yml no cambia ni una línea, y esa es la decisión central: hacerlo allí habría hecho que cada publicación del sitio esperara un build de Tauri de tres plataformas (publish-site declara needs sobre los jobs de empaquetado) y habría duplicado los gates que ci.yml ya corre sobre el mismo commit. Los tres presupuestos de tamaño gatean también esta ruta, con test que exige el mismo valor en los dos archivos; el artefacto se llama meltemi-unsigned-<SO>-<sha> y caduca a los 7 días; el aviso de «sin firmar» viaja al resumen del run y dentro del artefacto. Costo dicho sin maquillar —tres jobs caros por push— con dos diales declarados para bajarlo: el bloque on: y la matriz de plataformas. Cuatro deltas ADDED sobre release-distribution, cero dependencias nuevas.

Desenlace (2026-08-09) — verificada en runner real. El primer push a main tras el merge (commit 5b979c5c, 2026-08-06) dejó el run de Build verde en 15m3s con sus tres artefactos descargables; el de macOS, abierto y no inferido, trae el DMG normalizado y el tar.gz con los cuatro binarios —los dos adaptadores propios incluidos— más SHA256SUMS y el UNSIGNED-BUILD.txt íntegro. Tiempos de pared, el dato con el que se decide la cadencia: Linux 7m36s · macOS 9m35s · Windows 14m59s. Los tres pasos de presupuesto cerraron verdes, así que gatean esta ruta de hecho. No se creó release alguna y releases/latest sigue en la v0.1.0 firmada. Evidencia completa de los seis puntos en tasks.md 4.2. La segunda corrida (commit 5f01907, mismo día) salió verde en 3m29s / 3m36s / 5m16s: el par caché fría ~15 min, caché caliente ~5 min es el número real de la cadencia, un tercio de lo que la propuesta declaró para el caso normal.

Hallazgo del mismo push, ajeno a esta change y ya resuelto por sí solo: publish-site de release.yml arrancó a los 71 segundos —sin esperar empaquetado alguno, que era la razón entera de no tocar aquel archivo— pero su actions/deploy-pages@v4 agotó la espera («Timeout reached, aborting!», 10m9s), y el del run del tag v0.1.1, empujado 18 segundos después, murió con «Deployment cancelled». En el push del 2026-08-09 el mismo job completó con éxito, así que la causa fue la concurrencia por el entorno Pages, no una rotura del pipeline. Queda escrito para que un rojo idéntico no se lea mañana como defecto nuevo. Siguen abiertos, y son del mantenedor porque tocan credenciales y configuración del repositorio: el HTTPS sin provisionar (https_enforced: false) y el borrador v0.1.1 sin publicar que dejó aquel run de tag.

Cuatro días sin gate verde, y lo que dejaron pasar (2026-08-09)

Sección titulada «Cuatro días sin gate verde, y lo que dejaron pasar (2026-08-09)»

Al empujar la tanda de propuestas de este día, CI salió rojo en las tres plataformas — y el diagnóstico dejó ver algo más grande que su causa inmediata. Entre el 2026-08-06 y el 2026-08-09 no corrió ni un solo run de ci.yml: toda la tanda UX (divisor, pestañas, avisos, flota por suscripción, piel de Chrome) entró a main sin pasar por los gates, y su archivado se apoyó en corridas locales. Lo que eso dejó pasar, encontrado y corregido en el acto:

  • Un ReferenceError vivo en el camino de permisos: stores.ts llamaba a pushNotice en los manejadores de permission/request y permission/timeout, pero el módulo solo la re-exportaba (export { … } from "./notices", que no crea binding local). Un permiso llegado por push reventaba el manejador: sin aviso y sin el refreshPending() que venía después. Es exactamente el camino que espera-humana y sesion-esperando construyeron. Lo introdujo cromo-que-no-estorba al sacar los avisos a su módulo puro.
  • Cuatro claves i18n duplicadas (fleet.level.declared y fleet.level.verified, en los dos idiomas), de flota-por-suscripcion.
  • MIN_TAB_PX importado y no usado en TabStrip.svelte, con el 96px duplicado a mano en su CSS — la constante sigue en tab-strip.ts y piel-de-pestanas la reconectará.
  • App.svelte comparaba view === "sessions" sobre un $state que TypeScript estrechaba al literal "home" desde que el compositor pasó a ser la vista de aterrizaje; anotado como $state<ViewId> para que el estado vuelva a tener el tipo que dice tener.

Y la causa inmediata del rojo: un aviso de seguridad publicado entre ambos pushes — nanoid <3.3.17 (high, GHSA-2v37-7h3g-55p8) y postcss (moderate), ambos transitivos de Vite. npm audit fix los subió a 3.3.18 y 8.5.26 sin tocar package.json. Lección de método, no anécdota: el gate solo protege si corre; conviene mirar que corrió antes de dar una tanda por cerrada.

salida-que-se-lee — abierta el 2026-08-15, vía rápida

Sección titulada «salida-que-se-lee — abierta el 2026-08-15, vía rápida»

El mantenedor puso la salida de OpenSpec junto a la nuestra y la comparación no admitía discusión: sin resumen (los totales había que sumarlos a ojo), sin alineación (treinta y seis filas que no se recorren en vertical) y sin color (activa y archivada, 7/7 y 0/9, se ven igual). Pidió además formatos de salida al estilo de Kubernetes.

--json era un booleano, y un booleano no admite un tercer formato sin convertirse en dos que pueden contradecirse: ahora es un enum resuelto una vez, y --json --yaml se rehúsa por nombre en vez de resolverse por el último flag. El emisor YAML es propio y la change queda con cero dependencias: serde_yaml está archivado por su autor desde 2024 —adoptarlo pediría un ignore en deny.toml elegido a propósito— y YAML 1.2 es superconjunto de JSON, así que emitir toda cadena entre comillas dobles con el escapado de JSON es válido por construcción y los casos de borde temidos no llegan a existir.

El color no carga significado: estado es la palabra, progreso son las cifras, la compuerta lo dice en texto, un artefacto ausente es un punto donde iría una letra. El test renderiza dos veces, quita los escapes de la pintada y exige que sean idénticas — de modo que el color no puede empezar a significar algo más adelante sin que la suite lo note. Y sin TTY no se pinta, que es lo que hace el cambio compatible byte a byte para todo script existente y la razón de que ningún requisito vivo necesitara modificarse.

Tres hallazgos de implementación: padear después de pintar alinea los escapes en vez de las letras (las secuencias ANSI no ocupan ancho); la última columna no debe padearse (solo produce espacios finales invisibles); y el filtro de un test atrapaba la línea de resumen junto con las filas. Nota: docs/qa/2026-08-15-salida-que-se-lee-smoke.md.

Deuda declarada: que el terminal pinte de verdad no se automatizó — capturar la salida la convierte en un pipe, y en un pipe el color se apaga por diseño, así que la medición destruiría lo que mide. Levantar una pseudo-terminal (ConPTY) sería su propia change.

acceso-remoto-en-dos-vias — abierta el 2026-08-09, vía rápida

Sección titulada «acceso-remoto-en-dos-vias — abierta el 2026-08-09, vía rápida»

Nace de una exploración con el mantenedor sobre el compañero móvil, y de tres frases suyas: la combinación debe funcionar «en dos vías» (PC o CEL fuera de casa, el trabajo sigue), varios Meltemi en varios equipos con varios teléfonos, e idealmente PC↔móvil directo con el hub como respaldo aceptable.

Dos hallazgos la definen. El agujero con nombre: Windows no podía ser el extremo servido, porque su endpoint es un named pipe y ninguna forma de reenvío SSH lo alcanza — toda ruta termina en algo que corre dentro de esa máquina. Ese último metro era un verbo que faltaba, meltemi bridge, que conecta el endpoint local con su propio stdio; ssh <pc> meltemi bridge es entonces un canal JSON-RPC completo en las tres plataformas, y la limitación de Windows queda arrinconada donde no molesta. El patrón sin dueño: «en dos vías» se resuelve con una sola regla — nadie recibe conexiones, ambos extremos marcan hacia afuera a un punto de encuentro del usuario. El túnel inverso reenvía el puerto TCP del sshd del PC, que el OpenSSH de Windows sí reenvía, así que el pipe no viaja por ningún túnel.

Todo lo que va más allá del verbo es infraestructura del usuario —bastión, malla WireGuard con plano de control autohospedado, identidad— y por eso se documenta como frontera en vez de implementarse: licencias verificadas, nada entra al workspace, el daemon sigue ciego y el transporte final sigue siendo el SSH del usuario hacia el socket local. Ningún requisito vivo se modifica.

Dos defectos que solo la medición encontró, ambos en la vuelta daemon→cliente: tokio::io::copy vacía solo al EOF (un protocolo de petición/respuesta se ahoga esperando un búfer que solo llena la respuesta que se retiene); y —la causa real— un abrazo mortal del candado de stdout, porque main retiene io::stdout().lock() durante todo el dispatch y el candado de Rust es reentrante por hilo, mientras tokio::io::stdout() escribe desde el pool de bloqueo. El puente escribe ahora por el escritor que el proceso ya bloqueó. Nota: docs/qa/2026-08-15-acceso-remoto-en-dos-vias-smoke.md.

Deuda declarada: el tramo sshd → bridge no se ejercitó — el servidor OpenSSH de Windows está NotPresent en la máquina del mantenedor e instalarlo exige privilegios y toca su superficie de seguridad. Queda por medir que el shell por defecto de sshd no altere el flujo de bytes. Notas de fase 3 capturadas para companero-movil: identidad BYO por certificados SSH de vida corta emitidos por el IdP del usuario, selector multi-máquina como concepto de la app (cada meltemid sigue siendo de su máquina), y el aviso de espera autohospedado.

rama-por-change — abierta el 2026-08-16, vía completa

Sección titulada «rama-por-change — abierta el 2026-08-16, vía completa»

El mantenedor instauró el flujo con una frase —cada change «en ramas separadas por change y al terminar […] merge a main»— después de que un git add amplio arrastrara archivos ajenos tres veces en un día entre sesiones concurrentes commiteando sobre el mismo árbol. Meltemi ya orquestaba worktrees, pero en el eje de las carreras (change×tarea×agente); esta change añade el eje que el flujo necesita: el taller de la change, con su rama de nombre desnudo y su aterrizaje.

change/workspace es «dame», no «crea»: idempotente con reencuentro declarado, creado desde la punta de la rama por defecto (detectada, no asumida). La propiedad la da el registro, no un namespace: la rama homónima ajena se rehúsa sin tocarse solo en el camino implícito — nombrarla con --branch es consentir, y --unique acuña un taller con sufijo que jamás colisiona (los dos flags se excluyen con palabras, como --json --yaml). change/land previsualiza sin confirm y fusiona --no-ff con él; el conflicto se aborta al instante y se entrega al git del usuario. Retirar un taller con commits sin aterrizar exige confirmación que dice cuántos, y la rama nunca se borra. La raíz gestionada queda excluida por info/exclude, no por el .gitignore versionado. Paridad §4 pagada por el registro obligatorio; doce escenarios cubiertos por e2e contra fixtures (uno con rama por defecto trunk).

cromo-que-no-estorba — abierta el 2026-08-08, vía rápida

Sección titulada «cromo-que-no-estorba — abierta el 2026-08-08, vía rápida»

Tres frases del mantenedor sobre una captura: el scroll del panel derecho, los mensajes que «se quedan pegados» y la paleta que no cierra al hacer clic fuera. El cajón declaraba overflow: auto en los dos ejes con 268 px fijos, así que una ruta larga sacaba barra horizontal; ahora es un solo eje y el contenido se parte. Los avisos no caducaban ninguno, lo cual es obligatorio solo para lo que la spec nombra —un vencimiento «no se descarta en silencio»— y no para un «enlace creado»: ahora los informativos se retiran a los 6 s y los de advertencia y error no tienen reloj, probado por ausencia avanzando cien veces el plazo; apuntar o enfocar detiene la cuenta y salir la reinicia. Y el velo de la paleta no tenía manejador de clic mientras el del conmutador sí: en vez de arreglar ese caso, un barrido exige cierre en todos los velos y encontró otros cuatro. La política de avisos salió a su propio módulo puro, porque el store no es importable bajo node y una obligación de spec merece un test que corra. Nota: docs/qa/2026-08-08-cromo-que-no-estorba-smoke.md.

flota-por-suscripcion — abierta el 2026-08-09, vía rápida

Sección titulada «flota-por-suscripcion — abierta el 2026-08-09, vía rápida»

El mantenedor dijo que la flota «no permite configurar varios agentes de un tipo». Lo que veía era cierto; lo que suponía, no: enlazar varias ya funcionaba y el smoke de la change anterior lo había fotografiado sin buscarlo. Lo que faltaba era la lectura: una fila de perfil nunca decía de qué agente era, aunque el contrato lleva underlyingAgent desde flota-multiproveedor y el CLI ya imprime (profile → claude-code). La superficie que lo decía era la terminal; la que lo escondía, la gráfica. Ahora cada agente va seguido de sus suscripciones, cada una diciendo «suscripción de X» como texto —la sangría solo acompaña—, con el recuento en el agente; una suscripción cuyo agente no está en el catálogo se lista marcada, con el id que declara, en vez de desaparecer. De paso se cumple un requisito vivo de integration-levels que la superficie incumplía: el nivel se dice «declarado» o «verificado» con palabras y no con un ✓ a secas, que es justo lo que esa spec prohíbe. Nota: docs/qa/2026-08-09-flota-por-suscripcion-smoke.md.

pestanas-como-chrome — abierta el 2026-08-09

Sección titulada «pestanas-como-chrome — abierta el 2026-08-09»

«El sistema de tabs quiero que se parezca al de google chrome», con grupos y botones < >. La tira envolvía —flex-wrap: wrap— y cinco sesiones ya producían una segunda fila que empujaba el contenido. Ahora es una sola fila: las pestañas encogen hasta un mínimo legible y solo entonces la tira se desplaza, con controles que existen únicamente mientras hay desbordamiento, medido con ResizeObserver, y que se deshabilitan en su extremo en vez de esconderse. La pestaña activa se trae a la vista con nearest, sin lo cual las flechas del patrón ARIA mueven el foco fuera de pantalla. Lo que no se copia de Chrome es su respuesta al desbordamiento —Chrome encoge hasta el favicon y nunca desplaza—: el mantenedor pidió las flechas y la petición manda sobre la referencia. Los grupos llevan nombre y color; el color identifica y el nombre viaja en el nombre accesible de cada pestaña, plegar declara cuántas guarda y no cierra ninguna, y si la activa estaba dentro, la actividad sale a una pestaña visible. Se agrupa por menú y no arrastrando, porque el equivalente accesible del arrastre es otra conversación. Nota: docs/qa/2026-08-09-pestanas-como-chrome-smoke.md.

Deuda declarada de esta tanda: las pestañas y sus grupos no se persisten entre arranques (sidebar-ajustable-y-pestanas D7, heredado); si se persisten, la primera tarea de esa change es medir el arranque con ocho pestañas. Sigue pendiente la auditoría de intuitividad que el mantenedor pidió como barrido completo de la aplicación.

Hallazgo del smoke de pensamiento-a-la-vista (2026-08-10), anotado y no colado: al reconstruir una conversación desde el log, el turno de una sesión ya terminada no se marca como cerrado. Medido con veinte segundos de espera activa sobre el binario: no se renderiza el indicador de fin de turno y, en consecuencia, el pensamiento queda desplegado en reposo. El log contiene turn_completed y el pliegue tiene su rama para marcarlo (conversation.ts:301-308), así que el defecto está en el camino que reconstruye desde el log, no en el dato ni en la regla nueva — y afecta igual al indicador de fin de turno, que es anterior. Candidata a vía rápida sobre gui-shell. Evidencia en docs/qa/2026-08-10-pensamiento-a-la-vista-smoke.md.

Flake conocido (2026-08-09): with_no_clients_the_constitutional_deny_ fires_after_the_grace (core/meltemid/tests/e2e_permisos.rs:369) falló una vez solo en Windows tras siete runs verdes. No es una regresión: su espera es un sondeo de 200 × 50 ms —diez segundos— a que la sesión llegue a ended, y en un runner cargado eso se agota. Reejecutado, pasó. Si reincide, el arreglo no es reintentar sino ensanchar el margen del sondeo, que es lo único que la prueba mide de más: el escenario es la denegación constitucional, no la velocidad del runner.

Hallazgo del smoke de piel-de-pestanas (2026-08-09), anotado y no colado: el CLI guarda la raíz del proyecto tal como se la escriben. meltemi session "…" . deja sesiones cuyo projectRoot es el literal ., mientras meltemi projects sí canonicaliza y muestra la ruta absoluta. En la GUI eso produce dos nodos: el proyecto real con 0 sesiones y un nodo inferido llamado . con todas ellas. Con ruta absoluta el árbol es correcto. Es la misma clase de defecto que la tanda del 2026-07-31 cerró por otras puertas («Spell a project’s root the same way whichever door it comes through»), y esta quedó abierta. Candidata a vía rápida; su casa natural es project-registry. Evidencia en docs/qa/2026-08-09-piel-de-pestanas-smoke.md.

harness-global-y-por-agente — abierta el 2026-08-09, implementada el 2026-09-15

Sección titulada «harness-global-y-por-agente — abierta el 2026-08-09, implementada el 2026-09-15»

La directiva del mantenedor: definir una sola vez el comportamiento base y las tecnologías —«el backend siempre es FastAPI y usa las tools xxx»— y ajustarlo por agente y por proyecto. La palabra «harness» queda para esto (rules, skills, agents, hooks); el TOML del motor propio pasa a llamarse manifiesto del motor (nota terminológica en motor-propio-byok). Fase 1: cuatro ámbitos con la precedencia vigente (global → global por-agente → proyecto → proyecto por-agente), pilar Rules con el formato de FDH tal cual (RULE.md con scope por glob — la fábrica del mantenedor, CLI Go v0.4.1 en producción, se reutiliza en vez de reinventarse), proyección de las capas nuevas por el único escritor (meltemi project, bloques gestionados; lo global del usuario jamás entra a archivos del repo) y la vista efectiva ×3 al estilo git config --show-origin: por agente, qué le aplica y de qué capa viene cada pieza. Skills, Hooks y Subagentes quedan nombrados como changes futuras (harness-skills, harness-hooks, harness-subagentes) con sus pruebas §6 y §2 por delante; los bundles con nombre y la alineación del lado FDH, también. Capability nueva agent-harness; spec-full deliberado.

Cerrada 25/25, verify 15/15. Tres hallazgos que solo aparecieron al leer los archivos de verdad. (1) El fixture con los cuatro RULE.md reales de FDH encontró un defecto anterior a esta change: parse_list partía por cada coma y el scope real ["**/*.{ts,tsx}"] se rompía en dos globs que nadie escribió — ningún archivo de rumbo/ podía hallarlo porque ninguno ha llevado nunca una coma. (2) Verificar los destinos de ámbito usuario produjo dos hechos que ninguna suposición habría dado: Codex lee AGENTS.override.md en vez de AGENTS.md cuando el override existe —escribir igual llenaría un archivo que nadie lee y parecería haber funcionado— y su directorio se mueve con CODEX_HOME. (3) agents_supported de FDH dice codex y este catálogo dice codex-cli: los vocabularios no coinciden, así que el campo se conserva, se muestra y no gobierna nada — quién recibe una regla lo decide el eje per-agent/<id>/, que usa los ids de este catálogo.

El guardián de «lo global del usuario jamás entra al repositorio» quedó estructural: la función que compila lo de repositorio no recibe las fuentes globales, así que no hay parámetro por donde entren. Un if se olvida en la siguiente refactorización; una firma que no admite el dato, no.

Y el cierre encontró lo suyo: verify dio 14/15 porque el escenario de la CLI estaba marcado hecho sin test que lo enlazara — el verbo existía y nadie lo probaba. Documentación en docs/harness.md.

familia-por-titulo — abierta el 2026-09-16, vía rápida

Sección titulada «familia-por-titulo — abierta el 2026-09-16, vía rápida»

Defecto en main, no idea nueva: desktop/ui/tests/forms.test.ts llevaba rojo el gate «every form resolves to a schema of its own family» desde que rama-por-change añadió change/workspace y change/land. harness-global-y-por-agente lo encontró al cerrar y lo anotó sin colarlo (tasks 6.3); esta change lo cobra por la puerta de siempre.

El test no fallaba por un contrato roto sino por una regla que el contrato nunca tuvo. El generador liga método→schema por el title del schema (claimsMethod, gen-method-forms.mjs:49–56), no por el nombre del archivo: el nombre es una etiqueta que viaja al resultado, nunca una llave que se consulte. Y workspace.schema.json no es una anomalía — es el cuarto miembro de un grupo que ya tenía tres: implement (sdd/implement), validate (sdd/validate) y verify-archive (sdd/verify · sdd/verify-mark · sdd/archive) llevan todos el nombre de sus verbos y no el de su familia, y son exactamente las tres entradas que sostenían la lista de excepciones del test. Por eso no se renombró nada: renombrar habría cambiado el contrato para que una heurística de test dejara de quejarse, y para ser honesto el archivo habría tenido que partirse en dos, porque aloja landParams tanto como workspaceParams.

Dos hechos que el mensaje del test escondía: change/land fallaba igual —no existe land.schema.json y el assert cortaba en el primero—, y cuatro de las siete entradas de la lista son inertes: change, spec, repo-map y commit ya pasan por file.startsWith(family).

Propuesta futura anotada, no colada (design D3): derivar la lista de los title del contrato en vez de escribirla a mano, lo que vigilaría la ligadura real en lugar de la forma de los nombres y haría imposible esta deriva; con ella desaparecerían solas las cuatro entradas inertes.

compositor-que-trabaja — abierta e implementada el 2026-08-09

Sección titulada «compositor-que-trabaja — abierta e implementada el 2026-08-09»

Home.svelte llevaba class:busy desde el día que se escribió y no había una sola regla que lo pintara. Ahora la tiene: el viento de la marca recorriendo el borde del compositor mientras un agente trabaja, y ■ Detener junto al envío, con la misma confirmación y el mismo verbo que el acceso del encabezado, que se conserva.

Es la primera change que enmienda el sistema de diseño, y lo hace por escrito en vez de contradecirlo: Motion gana la clase «indicador ambiental de trabajo» (uno por vista, bucle lento, solo transform u opacidad, jamás layout, solo mientras un agente trabaja) y la reserva de marca gana una excepción, redactada con su propio tope — «nada más en la superficie puede reclamarla; una segunda cosa vistiendo el degradado convierte a las dos en decoración».

Tres hallazgos del código cambiaron decisiones. El kill-switch global de movimiento reducido no apaga: acorta duraciones, y habría dejado la luz pintada y detenida en una posición cualquiera — el smoke lo midió (display: none y animation: 1e-05s), así que la regla propia está probada y no argumentada. LIVE incluye waiting_permission, de modo que reutilizarlo habría encendido la luz justo donde la change quiere apagarla: una luz girando mientras el agente espera al humano miente sobre quién debe actuar. Y la acción primaria pintaba el degradado con un literal suelto teniendo --mel-wind declarado, lo que se corrigió aquí porque escribir la excepción de marca y dejar el literal sería enmendar la regla y romperla la misma tarde.

Nota: docs/qa/2026-08-09-compositor-que-trabaja-smoke.md, que incluye la trampa de método que estuvo a punto de convertirse en un falso defecto — un driver que inyecta nodos contamina toda medición posterior.

titulo-de-sesion — abierta e implementada el 2026-08-09

Sección titulada «titulo-de-sesion — abierta e implementada el 2026-08-09»

Nace de lo que el smoke de piel-de-pestanas fotografió sin buscarlo: seis pestañas diciendo mock a296f430, mock 929240ed, mock 39597c6f — la misma palabra y ocho caracteres de hex, seis veces. El daemon deriva ahora el nombre de la frase que abrió la sesión, en local y sin modelo (§5: pedirle a la sesión de pago del usuario que se nombre gastaría sus tokens y pondría en su log palabras que no escribió).

Leer el código antes de escribir el design encontró dos trampas que la propuesta no podía conocer. La primera es la que más habría dolido: el índice pliega last-wins y merge_into solo copia los campos que enumera; el registro de cierre no lleva título, así que sin su propia rama el nombre se habría visto mientras la sesión corría y desaparecido al terminar — un defecto de datos con el disfraz de uno de pintado. La segunda: la instrucción existe dos veces, como se escribió y con las referencias @ expandidas; el título sale de la primera, y se corta por caracteres y jamás por bytes (el pozo de texto-intacto-al-agente).

Dos decisiones que la propuesta dejaba abiertas quedaron cerradas: una calle de carrera no recibe título —no nace de una frase— y reanudar conserva el suyo en vez de re-derivarlo. Y una tercera se enmendó al implementar: los turnos de autoría SDD tampoco lo reciben, porque a run_turn no llega la frase del usuario sino un prompt que compone el método; nombrar con texto generado es el mismo error que nombrar con una referencia expandida.

Cerrada 13/13 tareas, verify 11/11 sin marcas manuales. Los tres escenarios de orden y ausencia (que el título se tome antes de expandir, que las rutas sin frase no lo inventen, que el resume herede) se pinean contra el código que decide, porque un e2e vería el resultado y no el orden; la confirmación conducida es el smoke, que además midió la regla de ambigüedad en sus dos sentidos. Nota: docs/qa/2026-08-09-titulo-de-sesion-smoke.md.

barra-de-estado-agentica — abierta el 2026-08-09, vía rápida candidata

Sección titulada «barra-de-estado-agentica — abierta el 2026-08-09, vía rápida candidata»

Primer hallazgo capturado de la auditoría de intuitividad: el mantenedor pidió «una barra inferior de estado como VS Code e IntelliJ» — y la barra existe (StatusBar.svelte, especificada en gui-shell), tan escueta que su propio mantenedor no la registró como tal. La change la hace hablar el idioma del dominio en vez del de un editor: proyecto activo, change activa con su gate (gatePending ya viaja en el contrato), sesiones por estado en vez del plano «N en curso», y consumo de tokens de las sesiones activas donde esté medido — con la frontera de honestidad de analitica-consumo-local a la vista, porque ACP no transporta usage (los niveles 1 y 2 leen «no reportado» hasta la extensión de usage ya nombrada en motor-propio-byok). Segmentos accionables (clic navega a la vista dueña), prioridad declarada al encoger, y las mismas verdades nuevas en el chrome de la TUI; el footer de atajos de la TUI no se toca. Exclusión escrita: Ln/Col, encoding y toda señal de editor que el rumbo excluye. Deltas ADDED-only sobre gui-shell y tui-shell (más local-analytics si el design pide la consulta por sesión), cero dependencias nuevas.

piel-de-pestanas — abierta el 2026-08-09, vía rápida

Sección titulada «piel-de-pestanas — abierta el 2026-08-09, vía rápida»

Segunda captura de la auditoría de intuitividad, con la captura de Chrome al lado: «el manejo de tabs está feo». pestanas-como-chrome entregó la estructura (una fila, controles medidos, grupos) y la piel quedó en el mínimo. El diagnóstico tiene cinco causas leídas en el código: la tira no tiene capa propia de fondo (la activa no tiene de dónde levantarse), la activa se marca con borde de acento (se lee como input, no como pestaña), cero hover, cada pestaña carga su propia caja de 1 px con la X siempre visible, y el estado viaja como palabra repetida en las N pestañas. La change viste la anatomía de Chrome: capa de tira, activa unida al panel con curvas de unión (radial-gradient, dentro del presupuesto cross-webview), separadores solo entre inactivas, hover honesto, X revelada en hover/foco con Delete como camino de teclado vigente, estado comprimido a glifo con nombre accesible, y franja de color del grupo por pestaña. Medidas como constantes testeables en tab-strip.ts. ADDED-only sobre gui-shell; cero daemon, cero paridad.

«Diferenciar qué agente y a qué pertenece»: una pestaña dice hoy mock-agent 97040fb6 y con seis sesiones del mismo agente la tira es seis veces la misma palabra. El daemon deriva el título en local al iniciar (primera línea de la instrucción, truncado honesto) — en el daemon y no en un cliente, porque un título calculado en la GUI sería feature de una superficie (§4) y dos clientes no deben mostrar dos títulos para la misma sesión. sessionInfo gana title opcional (histórico sin migrar, degradación honesta), session_started lo lleva, el resume lo hereda. La pestaña pasa a avatar del agente + título, con el proyecto antepuesto solo cuando las pestañas abiertas cruzan más de un proyecto; la TUI lo adopta en su lista. Generarlo con modelo queda declarado como futuro opt-in de motor-propio-byok: inyectar un prompt oculto en la sesión de pago del usuario gastaría sus tokens en algo que no pidió y pondría en su log palabras que no escribió. Vía completa; ADDED sobre acp-session, gui-shell, tui-shell.

compositor-que-trabaja — abierta el 2026-08-09, vía rápida

Sección titulada «compositor-que-trabaja — abierta el 2026-08-09, vía rápida»

La referencia del mantenedor es Copilot: una luz que recorre el borde de la caja mientras se procesa. El gancho existe (class:busy sin CSS que lo use) y la señal falta donde el usuario va a escribir lo siguiente. El anillo corre con el degradado de marca (--mel-aegean → --mel-wind: el viento recorriendo el borde mientras las velas trabajan) por transform: rotate() sobre conic-gradient recortado — sin @property, sin mask-composite —, se enciende en el Home al enviar y en el detalle con state ∈ {starting, active}, y se apaga en waiting_permission: esperándote no es trabajando. Reduced-motion cae al fallback que el design system ya prescribe. Trae el ■ Detener al compositor con el mismo ConfirmDialog (decisión del mantenedor: la confirmación se queda). El gate único carga la enmienda al sistema de diseño que esto exige por escrito: Motion gana la clase «indicador ambiental de trabajo» (uno por vista, lento, jamás layout) y la reserva de marca gana su única excepción. ADDED-only sobre gui-shell.

El gesto que falta entre detener y complementar: el Esc de Claude Code — «no sigas por ahí; haz esto» sin perder la sesión. No es hueco casual sino carrera cerrada a propósito: el cancel marca la cola cancelada (session.rs) para que ninguna instrucción tardía entre a un turno que no correrá, y el bucle ACP rompe incondicionalmente en Cancelled. Imitar la interrupción desde un cliente es exactamente esa carrera; la forma correcta es el verbo atómico: session/direct con interrupt — encolar primero, señalar después, y un borde de turno que distingue cancel de sesión (rompe, como hoy) de interrupción nuestra con relevo (drena a Cancelled y despacha lo encolado). ACP ya es por-turno; los adaptadores propios no se tocan (su spec ya exige drenar la cancelación con la verdad). Interrumpir en waiting_permission resuelve la petición como cancelada, registrada; el log debe distinguir «el agente se detuvo» de «el humano lo interrumpió». GUI: «Interrumpir y enviar» junto a «Encolar» cuando hay texto; TUI: el mismo gesto (paridad §4 servida en la change). Mock-agent gana el escenario e2e. Vía completa; deltas sobre acp-session, gui-shell, tui-shell y el schema session-direct.

preguntas-del-agente — abierta el 2026-08-09

Sección titulada «preguntas-del-agente — abierta el 2026-08-09»

Cuando el agente pregunta con opciones, la pregunta debe contestar-se donde se escribe, como Claude/Codex/Copilot: listado con la recomendada visible y una salida de texto libre al final. Lo notable es cuánto existe: request_permission transporta N opciones con nombre, la bandeja y la conversación ya las pintan con botones sobre la misma cola. Faltan la presentación (acople al compositor en waiting_permission, aparición sin animación de layout — regla dura vigente) y el emisor real: el adaptador de Claude rehúsa AskUserQuestion como interactive-only con una premisa que caducó — Meltemi es la interfaz. Sus propios tests prueban que la pregunta llega por el canal con su tool_use_id y que la respuesta transporta updatedInput: el cable existe de punta a punta. La change levanta el rehúso solo para esa herramienta y escribe la excepción al principio de input-intacto con su fundamento (en AskUserQuestion el input es el formulario). Texto libre con la verdad de cada protocolo: por el canal de Claude viaja en updatedInput; por ACP nativo no viaja (Selected | Cancelled) y el escape es interrumpir-y-relevar — depende de redirigir-turno. El mock-agent aprende a preguntar para e2e y demos. Vía completa; ADDED sobre own-adapters y gui-shell.

El mantenedor lo mostró con una captura: turno terminado, compositor muerto. La causa, verificada: el borde del turno cierra la cola en cuanto queda vacía (take_or_close, session.rs:88-101), el crate ACP mata el subproceso al drop y finalize_ok deregistra — no existe estado «esperando instrucciones», y toda la sesión vive dentro de un solo RPC síncrono. Lo que hoy parece persistencia es auto-resume (sesión nueva encadenada por resumed_from, que exige loadSession del agente y relanza el proceso por mensaje). La change: el borde espera en vez de cerrar (proceso vivo, encolar despierta), el arranque se desacopla del RPC por vía aditiva —la evidencia de uso que eventos-para-tardios dejó pedida—, política de idle explícita con finalize honesto (reason: idle, jamás completed fingido), y el estado «esperando instrucciones» visible en las tres superficies. Comparte borde con redirigir-turno: van adyacentes en el orden para no reabrir ese código dos veces. Vía completa; el riesgo nombrado son los subprocesos idle acumulados (la política es la mitigación y el QA mide el reposo).

pensamiento-a-la-vista — abierta el 2026-08-09, vía rápida candidata

Sección titulada «pensamiento-a-la-vista — abierta el 2026-08-09, vía rápida candidata»

«Ver la ejecución y la cadena de pensamiento en vivo como Codex/Claude Code/Copilot» — y el hallazgo de la auditoría de código: la cadena entera ya funciona. Los dos adaptadores propios reenvían el pensamiento en streaming (claude thinking_delta→AgentThoughtChunk con dedup; codex deltas de reasoning), el daemon reenvía verbatim, y la GUI ya pinta burbujas que crecen chunk a chunk. Dos eslabones flojos, exactos: el <details> colapsado de la GUI (SessionDetail.svelte:637-641) —el stream vivo existe pero hay que expandirlo a mano— y la TUI que reduce todo evento a [id] tipo (conn.rs:693-705), sin prosa ni pensamiento. La change destapa: expandido en vivo durante el turno en la GUI, pliegue conversacional en el drill-in de la TUI (espejo del fold de conversation.ts, con tope y gemelos ASCII), y la honestidad de nivel 3 dicha (headless no mapea reasoning; sin chunk no hay sección). Deltas ADDED sobre gui-shell y tui-shell; cero daemon, cero contrato, cero dependencias.

modos-de-autonomia — abierta el 2026-08-09

Sección titulada «modos-de-autonomia — abierta el 2026-08-09»

Pedido directo del mantenedor con la referencia de los productos vecinos (Manual / Accept edits / Plan / Auto / Bypass): saber por sesión «si pide más permisos para cada acción o actúa de forma independiente». El hallazgo que la abarata: el daemon ya compone posturas por sesión (explore corre deny_all, la autoría SDD allow_all, los interactivos cargan las reglas del disco; sdd/implement ya lleva autonomous: bool con «never autonomy by accident») — falta exponerlo. La change: campo mode aditivo que se traduce a un bundle sintético con ámbito propio, compuesto con las reglas del usuario en el punto único existente (la precedencia del motor es por ámbito, no por posición: el design extiende evaluate); Manual = todo pregunta, Semi = ediciones dentro del worktree pasan (contención por path_prefix; is_out_of_tree clasifica mando y red, no rutas), Autónomo = allow amplio salvo lo irreversible/fuera del árbol, que escala en todos los modos — §3 literal, y el deny sin clientes no se toca. Bypass no existirá: es frontera constitucional, no deuda. De paso se salda allow_meltemi_writes() (promete .meltemi/, devuelve allow_all). Chip de modo visible en las tres superficies y el modo escrito en el log y la bandeja. Vía completa: la matriz de composición modo×reglas tiene esquinas que el design enumera y pinea con tests.

modelo-y-esfuerzo-por-sesion — abierta el 2026-08-09

Sección titulada «modelo-y-esfuerzo-por-sesion — abierta el 2026-08-09»

La palanca de cuotas que el mantenedor pidió con sus capturas: elegir modelo y esfuerzo de razonamiento por sesión. Verificado: el app-server de Codex ya expone model/effort por turno y el adaptador propio los deja apagados a propósito citando §5; el de Claude no pasa --model pero el punto de inserción es limpio y ya lee el modelo que el CLI anuncia; los perfiles solo declaran agente+env; agent_resolved no registra el modelo (solo asoma por el meta providerModel del adaptador de Claude o por usage_reported de un nivel 3). Y ACP sí trae el vehículo: el esquema 1.4.0 del crate pineado define session config options (Model/ThoughtLevel) — la prueba §6 se endereza y la vía estándar se cablea. La change, gobernada entera por §5 y §6: model/effort como strings opacos en el contrato que el núcleo transporta sin interpretar y solo cada adaptador traduce (lo no soportado se rehúsa con diagnóstico); los perfiles ganan ambos campos («perfil = agente + cuenta + modelo», la unidad de administración de cuotas); chip y picker en el compositor con ficha que muestra solo lo que Meltemi sabe —sin precios ni créditos, que son negocio de terceros—; cambio a mitad de sesión donde el proveedor lo soporta, con el aviso honesto de la referencia («reinicia la caché del proveedor y puede aumentar el costo»); y agent_resolved gana el modelo efectivo. El ruteo automático «mejor modelo por tarea» queda rechazado para el core y nombrado como change futura declarativa (ruteo-declarativo-de-perfiles).

Sección titulada «sidebar-ajustable-y-pestanas — abierta el 2026-08-08»

Nace de una captura del mantenedor y tres frases: la línea divisoria entre las opciones y los proyectos «debe poder moverse», el scroll de la sección de proyectos «se ve fea», y las sesiones «deben ser tabs, de esa forma puedo tener varios tabs abiertos». Tres cosas de naturaleza distinta y una sola change, por una razón medible: el divisor fabrica la segunda barra de scroll —darle alto a nav obliga a overflow-y: auto y la columna de 216 px estrena otra barra clásica—, así que entregar la primera sin la segunda duplica el defecto del que trata la segunda.

Lo que la investigación encontró antes de escribir nada: la «línea» no era un elemento sino un border-top del encabezado PROYECTOS; no existía un solo pointerdown en toda la superficie de escritorio; no había ningún estilo de barra de desplazamiento en el repositorio, así que lo que se veía era el defecto de plataforma; y las sesiones se pisaban porque el shell guardaba un identificador que cuatro sitios sobrescribían —de ahí que un borrador escrito en una sesión sobreviviera dentro de otra.

Dos decisiones cargan el peso. Las pestañas van contenidas en la vista Sesiones y no sobre la región principal, porque las dos formas rivales modifican el mismo encabezado de requisito que lanzador-conversacional ya modifica en un delta sin archivar bloqueado en la firma del mantenedor: solo un delta ADDED puede fusionarse sin pisar texto ajeno. Y los paneles se montan y se ocultan en vez de desmontarse, que es lo que mantiene vivos transcript, búsqueda y borrador; el lado del daemon es seguro porque su conjunto de vigilancias es un HashSet por conexión sin tope, leído y citado, no supuesto.

El smoke conducido sobre el binario encontró cuatro cosas que el código fuente no podía enseñar, y todas se corrigieron: que scrollbar-width no hereda; que la barra angosta conserva sus botones de flecha en WebView2 y ninguna propiedad estándar los quita; que las dos familias de estilo de barra son excluyentes en Chromium —de ahí las dos ramas @supports—; y que el anillo de foco del separador parecía un campo de texto vacío. Nota completa en docs/qa/2026-08-08-sidebar-ajustable-y-pestanas-smoke.md.

Veinte escenarios, tres requisitos ADDED sobre gui-shell, cero dependencias, cero métodos del contrato, un solo archivo Rust de producto tocado.

Seguimientos nombrados: (1) adoptar TabStrip en el Editor, cuya tira propia no sigue el patrón ARIA; (2) un tope de líneas del transcript en la GUI —la TUI ya tiene el suyo— si ocho transcripts montados lo piden; (3) persistir el conjunto de pestañas al arrancar, cuya primera tarea sería medir el arranque con ocho.

sesiones-en-la-barra — abierta el 2026-09-06, implementada el 2026-09-15

Sección titulada «sesiones-en-la-barra — abierta el 2026-09-06, implementada el 2026-09-15»

Nace de la maqueta de acabado del shell y de cuatro frases del mantenedor: las sesiones «deben aparecer a la izquierda en el menú y diferenciadas por en curso, en pausa, esperando respuesta del usuario, detenido»; «lo que dice lista, no tiene sentido, no sirve para nada»; «al hacerle nueva sesión debe crear el tab y además dejar el cursor en el campo de texto con foco», con «ctrl + enter para enviar o ctrl + shift + enter para encolar mensaje»; y, al mirar la barra otra vez, «no veo dónde la gestión de tabs a la izquierda».

Las cuatro cosas son una sola pregunta —¿quién me necesita?— hecha desde el sitio donde se elige a quién atender. El contrato ya tiene los seis estados y la barra de estado ya los parte en trabajando / esperando / listas; lo que faltaba era usarlos donde se decide. Por eso el árbol gana cubetas dentro de cada proyecto (el proyecto sigue siendo el ámbito, la cubeta es el orden), la barra gana la sección «Abiertas» que es la tira vista de lado, y la pestaña «Lista» desaparece porque duplicaba la entrada Sesiones del menú.

Dos decisiones cargan el peso, y las dos nacieron de la revisión adversarial antes de escribir código. La primera: el compositor deja de ser una vista y pasa a ser la pestaña de llegada, que es lo que hace que «nueva sesión» cree su tab en vez de esconder los que ya hay; eso roza la frase de «Paridad de vistas y modelo de navegación» que lanzador-conversacional modifica sin archivar, así que la enmienda de esa frase se declara como deuda con nombre —la lleva quien archive segunda— en vez de darse por compuesta. La segunda: con un turno en vuelo, el acorde que despacha releva (interrumpe y envía, la puerta que redirigir-turno construyó) y el que encola deja la instrucción detrás; el texto normativo nunca llama «enviar» al primero, de modo que «Enviar no interrumpe» de conversational-session sigue siendo cierto palabra por palabra, y el compositor lo dice antes de que se pulse. El mapeo alterno —Ctrl+Enter encola, Ctrl+Shift+Enter releva— queda anotado en el design para que la compuerta lo decida.

Deuda declarada: la guardia migration.rs::SUPERSEDED no cubre gui-shell (la capability nació después de openspec/), así que el renombre del escenario de la lista se pinea con un test propio; y la tabla de cubetas vive dos veces —TypeScript y Rust no comparten función—, con un test de paridad que falla si divergen.

Cerrada 8/8, verify 34/34. Tres cosas que solo aparecieron al implementar.

(1) El design se equivocó en un hecho: daba por existente una guardia que prohíbe toda palabra de animación en Sidebar.svelte; ese archivo de tests ya no existe —se fundió en scenarios_shell.rs— y la prohibición solo cubría la bandeja. La guardia se escribió aquí, que es justo cuando se volvió portante: la barra pasó a contener la cubeta donde aterriza un permiso, y una fila que se deslizara sería movimiento bajo el cursor mientras se decide.

(2) Quitar la pestaña «Lista» destapó un fallo de accesibilidad: TabStrip ponía tabindex=0 solo en la pestaña seleccionada, y con la lista en pantalla ninguna lo estaría — un tablist sin nada en el orden de tabulación, o sea sin manera de entrar con el teclado. Ahora el tabindex sigue a un focusIndex que cae a la primera pestaña cuando no hay selección: ARIA pide exactamente una pestaña tabulable, nunca que una esté seleccionada.

(3) Dos decisiones que el design no había tomado y que el código obligó a tomar: si la sesión arranca mientras se lee otra pestaña, la pestaña nace igual pero el frente no se mueve (llevarse al usuario sería que la superficie decidiera dónde mira); y el compositor toma el cursor solo mientras es la pestaña al frente, porque su panel queda montado detrás de otra y un campo oculto que roba el foco escribe donde nadie ve.

Y el cierre encontró lo suyo: verify dio 33/34 porque el escenario de las teclas del terminal se daba por servido sin test que lo enlazara.

El smoke conducido sobre el binario encontró dos cosas más. La primera se corrigió aquí: a 216 px la cabecera leía «LISTAS PARA TU INSTRU… 1», y la culpa no era la frase sino el uppercase + letter-spacing heredados de .sectionTitle — un nombre de cubeta es una frase sobre sus filas, no el título de una región.

La segunda no se corrige aquí, y es la que importa: muestreando las cabeceras 80 veces alrededor de un turno real, la cubeta Trabajando nunca apareció. En la misma corrida el daemon respondió queued y el compositor dijo «el turno en curso sigue intacto» — o sea que había turno en vuelo y el listado de la superficie no lo sabía. refreshSessions() se llama al conectar, al conmutar de proyecto y al terminar un envío, nunca durante un turno; y de ese listado salen tanto el anillo de compositor-que-trabaja como el par de esta change. Es anterior a esta change —las dos anteriores ya dependían del mismo listado—, pero esta lo puso donde se ve. Sale a su propia change en vez de colarse: refrescar durante un turno es conducta sobre un store compartido, roza la regla de que la barra no anima, y hay que decidir si repregunta el cliente o empuja el daemon. Nota completa en docs/qa/2026-09-16-sesiones-en-la-barra-smoke.md.

identidad-propia — abierta el 2026-09-06, implementada el 2026-10-01, vía completa

Sección titulada «identidad-propia — abierta el 2026-09-06, implementada el 2026-10-01, vía completa»

Nace de una frase del mantenedor —«lo otro importante, inicio de sesión; sé que para esto hace falta un backend pero puede ser parte de la propuesta»— y de lo que ya había pedido para el móvil: «poder autenticarme en el cel con mi cuenta y ver las máquinas o instancias que están conectadas».

La respuesta empieza por lo que no se hace, porque tres guardianes lo prohíben a la vez: deny.toml no admite cliente HTTP ni pila TLS en el workspace, el webview no alcanza ningún origen https y su test lo pinea, y la constitución §3 mantiene al daemon sin puertos. Un flujo OIDC dentro de Meltemi rompería los tres, y docs/acceso-remoto.md ya había escrito que «Meltemi con login» exigiría enmienda fundacional. La maqueta de acabado que dibujaba un código de dispositivo dentro de la app se corrige por eso.

Lo que sí cabe es la identidad que la malla del usuario ya conoce: Headscale con su IdP hace el OIDC en el navegador del usuario al enlazar cada equipo, y el cliente oficial sabe localmente quién es y qué equipos hay. Meltemi lo lee por ese binario —la misma regla con la que ejecuta git y los agentes—, compone sin ejecutar jamás el gesto que enlaza un equipo (como subscription/link compone el login de una suscripción), y lo muestra en sus tres superficies antes de que el móvil lo enseñe. Cero dependencias nuevas, deny.toml intacto, «sin cuentas» sigue siendo literalmente cierto.

El único MODIFIED es sobre «El punto de encuentro en dos vías está documentado», que hoy manda que la identidad y el selector de máquinas queden como notas de fase 3: esta change convierte en capacidad la parte de la variante de malla y deja como nota lo que sigue siéndolo (certificados SSH del bastión, el selector que conecta, el aviso de espera).

Deuda declarada: la forma del JSON del cliente de malla no es verificable desde el repositorio, así que la primera tarea del daemon captura una salida real redactada como fixture antes de escribir el parser —un campo mal nombrado daría un parser verde en CI y un rehúso contra el cliente de verdad—. Y el test tui/tests/docs.rs pinea hoy la nota de fase 3 que la change reescribe: se reescribe con ella, conservando sus tres marcadores.

Implementada el 2026-10-01 (8/8). La deuda declarada arriba bloqueó la change cuatro días: en el equipo del mantenedor no hay cliente de malla instalado, y el design decía por qué no se podía saltar. Se desbloqueó por la vía más fuerte, no por un atajo: la forma se verificó contra las definiciones de tipo publicadas del propio cliente, fijadas en v1.102.5 (ipn/ipnstate/ipnstate.go, tailcfg/tailcfg.go), que es de donde el CLI serializa su JSON. Una captura muestra solo los campos que una máquina pobló en un estado; el tipo enumera todos con su etiqueta y su regla de presencia —y delató cuatro trampas que una captura en un equipo sano habría escondido: Self y CurrentTailnet son nulos sin conexión (justo el caso «sin enlazar»), LastSeen no lleva omitempty y un par en línea trae el tiempo cero (un parser ingenuo diría «visto: año 1»), las claves del mapa User son el id en decimal como cadena mientras el par lo trae como número (buscarlo sin convertir devuelve un usuario vacío contra el cliente real), y ShareeNode marca el equipo que otra persona compartió hacia dentro, que el propio status del cliente oculta por defecto. Cada una con su test.

Tres hallazgos más del camino. (1) El contrato traía tres cadenas y --exec necesita un argv: volver a partir la línea por espacios habría roto una ruta de cliente con espacio, que es el fallo exacto que las dos formas citadas existen para evitar, así que IdentityLinkResult gana args. (2) El rigor de los tests se midió neuterando el código, y de seis roturas deliberadas una no puso nada en rojo: nada cubría «BackendState dice Running pero Self es nulo», donde el handler panickeaba en vez de rehusar; ese test ahora existe. (3) El guardián de variables de estilo cazó cuatro reglas CSS que no habrían pintado nada (--sunken, --radius-1, --text-dim no existen en la piel).

Lo que queda, y queda dicho: una verificación de campo —correr meltemi identity una vez contra un cliente instalado y enlazado—, que no bloquea nada porque los nombres salen del tipo y no de una conjetura; y la corrección del tablero «Inicio de sesión» del lienzo de acabado, que vive fuera del árbol, en el artefacto publicado de la sesión de diseño: la forma construible está dibujada en design-system/ (sección 6b, con sus tres estados) y la edición del lienzo es acción del mantenedor, porque el repositorio no puede editar lo que no contiene.

Gobernanza de alcance (changes enmienda-edicion-movil y enmienda-agent-boss): la edición in situ de Fase 2 está acotada por la cerca de la spec edit-surface; el compañero móvil de Fase 3 (companero-movil, meltemi.md §10) es el puesto remoto del Agent Boss — monitorear/aprobar/revisar/dirigir, sin autoría, túnel SSH exclusivamente, aviso de espera opt-in autohospedado — por las specs mobile-companion y remote-access.

apagado-entero-y-modos — abierta el 2026-09-17, implementada el 2026-09-18, vía completa

Sección titulada «apagado-entero-y-modos — abierta el 2026-09-17, implementada el 2026-09-18, vía completa»

Nace de una revisión que el mantenedor pidió el 2026-09-17: contrastar nuestro enfoque de adaptadores con claudian (plugin de Obsidian, MIT, que pilota Claude Code, Codex, OpenCode, Grok y Pi) y decidir qué rescatar. La revisión —los 1.671 archivos del árbol, a fondo su modelo neutral, su capa ACP y los cinco proveedores— concluyó que nuestro enfoque resuelve lo mismo en una capa mejor: normalizamos en el estándar y no en un modelo de eventos propio (seis agentes de nivel 1 sin una línea de adaptador; ellos ~40 archivos por proveedor, incluso para los que hablan ACP nativo), los adaptadores son binarios gobernados fuera del proceso, Claude va por el binario oficial y no por el SDK que sus términos nombran, y los checkpoints son git para todos y no rewindFiles para uno. Lo que sí hacemos peor son dos cosas medidas, y esta change son esas dos.

Apagado entero. En Windows, un CLI instalado por npm es un shim .cmd bajo cmd.exe, y TerminateProcess sobre el shim deja vivo al node (o al binario nativo) de abajo. Reproducido con un shim y un Stop-Process: el nieto siguió vivo. Lo tenemos en las dos capas que lanzan proveedores: los adaptadores (supervisor.rs, kill tras la gracia y kill_on_drop) y el daemon, que delega el nivel 1 en AcpAgent del crate oficial, cuyo ChildGuard mata igual. La spec viva promete «no queda ningún proceso huérfano»; con un shim, hoy es falso. Remedio: un crate meltemi-process con un Job Object por proveedor y KILL_ON_JOB_CLOSE —termina el árbol a cualquier profundidad y, como cerrar el handle también termina, un crash del lanzador tampoco deja huérfanos—, en vez del taskkill /t de claudian, que no cubre el crash. Cero dependencias nuevas: windows-sys ya está pineado y gana una feature. El daemon pasa a lanzar él mismo por spawn_process (que el crate expone) y a conectar con Lines (también público), con lo que conoce el pid y lo anota.

Modos anunciados. El esquema ACP pineado trae modes y config_options en las respuestas de sesión; el daemon lee solo el segundo (acp.rs:257,283). Un agente que anuncie por el campo de modos aparece sin opción alguna — y modelo-y-esfuerzo concluyó «ningún proveedor anuncia opciones» mirando una sola forma. Tampoco se miran current_mode_update ni config_option_update. Remedio: leer las dos formas con la opción de configuración ganando entera, fijar el modo heredado por session/set_mode, y reflejar lo que el agente cambia por su cuenta. El contrato no cambia. Primera tarea de esa parte: verificar contra cada agente instalado qué forma anuncia, y persistirlo — para no repetir el error en dirección contraria.

Desenlace (implementada el 2026-09-18). Ocho tareas, ocho commits. El crate meltemi-process existe y lo usan las dos capas que lanzan proveedores. Los tres tests que miden el defecto se comprobaron mordiendo: neutralizada la adopción, el mock-agent sobrevive al final de la sesión y el test lo dice por su identificador; neutralizado el ruteo del verbo de modos y las dos ramas de forward_update, los tres e2e nuevos fallan. Dos desvíos del design, los dos escritos en el proposal: el contrato gana el evento de log agent_process —porque los dos eventos que podían llevar el pid se escriben antes del lanzamiento— y meltemid declara futures como dependencia directa, que ya viajaba en el lockfile.

Lo que la verificación manual encontró, y no es lo que se esperaba. De las seis entradas de nivel 1 del catálogo, solo opencode está instalada en este equipo, y puebla las dos formas a la vez: el campo de modos con build y plan, y las opciones de configuración con model (317 valores) y mode (categoría mode, los mismos dos modos). El design D6 planteó la precedencia como una regla para un caso incómodo; resultó ser el único caso real medible aquí, y fusionar las dos formas habría dado dos selectores de modo o uno con valores duplicados. La otra cara: la síntesis del campo viejo no queda ejercitada por ningún binario real —haría falta un agente que puebla modos y no opciones—, y docs/conformidad-manual.md lo dice con esas palabras en vez de dejarlo implícito. Hallazgo lateral: la conclusión D9 de modelo-y-esfuerzo-por-sesion («ningún proveedor pineado anuncia opciones de sesión») ya no es cierta, no por error de entonces sino por su fecha.

Deuda declarada de una decisión, no de un olvido. Reemplazar la lista anunciada entera (D7) tiene un costo: un agente que anunciara sus modos por el campo viejo y sus opciones por el nuevo perdería el selector de modo al cambiar cualquier otra opción, porque la lista que reemplaza no lleva modo. Volver a sintetizarlo ahí sería la fusión que esa misma regla prohíbe, así que se deja como está, escrito en el código y aquí. Ningún agente instalado tiene esa forma.

Lo que la revisión dejó para el próximo re-anclaje de Codex, medido contra el codex-cli 0.77.0 instalado: su esquema declara cuatro peticiones de servidor y el adaptador cubre las dos de la generación v2; turn/steer, item/tool/requestUserInput, item/permissions/requestApproval y thread/fork|rollback|compact no existen en 0.77.0. Cuando existan, una frase de claudian vale la pena: relevar a mitad de turno se resuelve como aceptado solo con la aceptación nativa definitiva; ante ambigüedad se rechaza, para que quien llamó conserve el texto.

Descartado por escrito: la vía del SDK (§2, §6), leer almacenes nativos de los agentes, inyectar prompt de sistema en la config de un agente, herramientas dinámicas, alias de nombres de método; y los huérfanos por crash del daemon en macOS/Linux, que son otra clase y otro remedio.

Prerrequisitos de daemon del Agent Boss (antes de companero-movil, sirven a TUI/GUI hoy)

Sección titulada «Prerrequisitos de daemon del Agent Boss (antes de companero-movil, sirven a TUI/GUI hoy)»
Change Alcance
✅ espera-humana (2026-07-26) Política de espera configurable ([permissions]: wait/implement-wait/no-client-grace): los flujos interactivos esperan al humano mientras haya cliente conectado; el fallo del push ya no resuelve la petición (la cola es la única fuente); sin clientes, denegación constitucional auditada tras la gracia
✅ sesion-esperando (2026-07-26) El daemon fija waiting_permission mientras una petición espera decisión (contado, para peticiones simultáneas) y change/list declara gatePending con el artefacto que espera, leído del estado del ciclo
✅ eventos-para-tardios (2026-07-26) Hub de eventos en el daemon y session/watch: la conexión que inició la sesión sigue recibiendo su stream, y cualquier otra lo pide por sesión. Diferido con razón escrita: las formas asíncronas de sdd/gate, sdd/review-decide y worktree/dispatch tocan la promesa ratificada de «pasos scriptables» y el stream las mitiga; entran como change propia si la evidencia de uso lo pide

companero-movil (propuesta abierta el 2026-09-24, 32º del orden del comparativo con Orca, sin arrancar hasta sus prerrequisitos; gobernada por las specs mobile-companion y remote-access: el puesto remoto del Agent Boss, cuatro verbos, sin autoría, túnel SSH exclusivamente, aviso de espera opt-in; su design debe resolver la frontera Windows del túnel — named pipe no reenviable por OpenSSH — sin abrir jamás un puerto de red del daemon) · funciones de equipo y organización (meltemi.md §3).

  • Organización (identidad paraguas): askenaz-dev — GitHub, npm. Paquetes npm futuros (SDK, fase 2): @askenaz-dev/<pkg>.
  • Producto: meltemi — dominio meltemi.dev, binarios meltemid/meltemi, crates meltemi/meltemid/meltemi-proto (crates.io es namespace plano, sin org).
  • Repositorio: github.com/askenaz-dev/meltemi.

Pendientes exclusivos del arquitecto (ningún agente debe hacerlos)

Sección titulada «Pendientes exclusivos del arquitecto (ningún agente debe hacerlos)»
  1. ✅ Ratificar meltemi.md, constitution.md y rumbo/ — hecho 2026-07-11. 1b. ⬜ Ratificar las enmiendas encadenadas de meltemi.md: v1.1→v1.2 (formato-artefactos-meltemi), v1.2→v1.3 (enmienda-edicion-movil) y v1.3→v1.4 (enmienda-agent-boss). Todas las versiones están aplicadas al documento; falta la firma del mantenedor fundador (method-bootstrap: la herramienta no se auto-ratifica). 1c. ⬜ Ratificar la enmienda de la promesa de producto — v1.4→v1.5 de meltemi.md y el párrafo «Qué es Meltemi» de .meltemi/rumbo/product.md (lanzador-conversacional, design D5, aplicada el 2026-07-31): toda sesión corre gobernada y la disciplina spec-first deja de presentarse como condición previa. A diferencia de las anteriores, esta ratificación es gate de archivo: sin la firma, lanzador-conversacional no archiva. Ambos textos están aplicados y marcados como pendientes en sus propios documentos. Al ratificar quedan dos cosas por hacer, en este orden: correr meltemi project (el bloque proyectado compila el rumbo) y refrescar la frase pública, que sigue diciendo lo viejo en README.md, LEEME.md, site/index.html y site/es/index.html — deliberadamente sin tocar, porque anunciar al mundo una promesa sin firmar sería exactamente lo que la enmienda evita. Con ese refresco va también la fila de docs/sesion-libre.md en el índice de documentación de los dos READMEs: enlazar «trabajo sin spec» bajo la promesa vieja publicaría la contradicción en vez de resolverla.
  2. Registrar: ✅ org GitHub askenaz-dev · ✅ org npm askenaz-dev · ✅ dominio meltemi.dev (comprado el 2026-07-25; servido por Cloudflare desde el 2026-10-21) · ⬜ crates meltemi, meltemid, meltemi-proto en crates.io (verificados LIBRES el 2026-07-11 — reservar con un cargo publish placeholder o en el primer release para evitar squatting).
  3. Decidir el mecanismo de firma del CLA cuando llegue #21.
  4. ⬜ Instalar ollama en la máquina de desarrollo (winget install Ollama.Ollama + ollama pull qwen2.5-coder:7b) para la pierna local de guia-modelos-locales y corrida-integrada; sin eso la receta se publica como «verificada en forma».
  5. ⬜ Decidir las versiones pineadas de Codex y OpenCode: la prueba del 2026-09-24 las dejó en 0.156.1 y 1.18.32. Para Codex la decisión ya tiene consecuencia en código: codex-al-dia re-ancló el esquema a 0.156.1, que es el piso del adaptador, y la corrida real del 2026-09-25 le dio nivel 2 con esa versión; volver a 0.77.0 ya no abre sesión. Para OpenCode sigue abierta (npm i -g opencode-ai@1.14.33 para volver).
  6. ⬜ Ratificar las dos enmiendas que traen abrir-con-lo-tuyo (rumbo: la terminal integrada como no-objetivo) y docs-en-el-sitio (§11: inglés como lengua fuente de la documentación de producto, método en español); ambas quedan aplicadas y marcadas pendientes hasta la firma.
  7. ⬜ Designar el segundo custodio de claves y publicar la clave minisign en el árbol Sustituido el 2026-10-23 por release-con-el-push: la firma manual se retira y no hay clave que publicar ni custodiar. Lo que queda del mantenedor: borrar el borrador v0.1.1 (borrado el 2026-10-23), apagar GitHub Pages en este repositorio y borrar su entorno github-pages (apagado y borrado el 2026-10-26; tarea 7.3 cerrada), adoptar el repositorio del IDE en github.tf de meltemi-web (aplicado el 2026-10-23, con GH_ADMIN_TOKEN como credencial del aviso por decisión del mantenedor) y designar quién sucede el control del repositorio y de la organización (sucesion-y-custodia, re-acotada).
  8. ⬜ La release que prueba un desarrollador (release-para-un-desarrollador, abierta el 2026-10-28; la tanda aterrizó el mismo día). En este orden: (a) correr docs/prueba-de-uno.md en la máquina de desarrollo con los agentes propios, sobre el build de integración del commit de main (artefacto meltemi-unsigned-Windows-<sha>), porque la release aún no existe; (b) escribir docs/qa/<fecha>-prueba-de-uno.md desde la plantilla del guion; (c) cargo run -p meltemi-release -- changelog 0.3.0 --report docs/qa/<fecha>-prueba-de-uno.md; (d) cargo run -p meltemi-release -- set-version 0.3.0 y push a main, que publica; (e) la fila «Cliente de escritorio» de meltemi-web, como change de ese repositorio. La ratificación 1c sigue siendo lo que deja a lanzador-conversacional fuera del CHANGELOG.md mientras no llegue.