diff --git a/.metodo/CHECKSUMS b/.metodo/CHECKSUMS index 7cb1a73..33a5469 100644 --- a/.metodo/CHECKSUMS +++ b/.metodo/CHECKSUMS @@ -1,2 +1,2 @@ -1d8ecd59e1b84da3f4c652b95f2212cdfcc60db1b4a0beb1cac96aeb6c6c0124 metodo.md +4cef3371e4ec9258933baf34cc23ee757542631a3e36c899f3bb9808ea8b3f3b metodo.md 3b35cfedfe36441d5c2b9b8e543657119a76daaebf6b317bcc4918b2cb7ca9b7 bin/metodo diff --git a/.metodo/metodo.md b/.metodo/metodo.md index a6f4fe2..2a4c0e1 100644 --- a/.metodo/metodo.md +++ b/.metodo/metodo.md @@ -20,11 +20,11 @@ doc en vez de repetirlo. No son teoría: cada uno lleva el caso real que lo ense > inlinar» viven dentro de su raíl.)* > Origen: destilados de la racha Hermes de julio 2026 (Fases 11/13, convergencia UI) **unificados -> con el método ya afinado en los workflows de Solidaria** (la fuente más madura). La lección de +> con el método ya afinado en los workflows del frente de aplicación** (el más maduro en método). La lección de > fondo: **una UI/gate honesto actúa como auditor del resto del sistema** — casi todos los raíles de > abajo nacieron de un "verde que mentía" cazado al construir bien la capa de encima. > -> **Meta-principio (de Solidaria): cada raíl se escribe CON LA CICATRIZ.** El humano (o un gate) +> **Meta-principio: cada raíl se escribe CON LA CICATRIZ.** El humano (o un gate) > caza lo que no cuadra → el raíl se escribe con el caso real que lo enseñó → no vuelve a pasar. Por > eso cada punto lleva su ejemplo: sin la cicatriz, un principio abstracto no se respeta. Este doc > crece añadiendo cicatrices, no teoría. @@ -85,7 +85,7 @@ en su sector**. Y es esto, dicho por él: ⛔ **Regla operativa**: antes de escribir *«pero si te comprometen X…»*, pregúntate **contra qué lo comparas**. Si la alternativa real que Xavier tiene hoy es peor, la propuesta no mejora nada — solo -añade dificultad, y eso lo prohíbe `I11·D23` (de `hermes-hub`: «la vara de medir es el COSTE +añade dificultad, y eso lo prohíbe `I11·D23` (del hub: «la vara de medir es el COSTE PARA EL OPERADOR»). @@ -94,7 +94,7 @@ AMENAZA, y leerla fuera de su ámbito la hace parecer mala.** *(Xavier, ordenand que no valore la captura de un hub — lo pondremos en el backlog por detrás, con su apartado. Ahora estamos en el apartado de **“y si capturan un edge”**, y para eso hay una CRL y unos procedimientos que mis equipos de hoy **ni tienen**».)* La orquestadora evaluó `D25` —del **edge**, apartado -`E14`; ⚠️ **sigue sin entrada en su registro**, ver `A43` de `hermes-edge/doc/AVISOS.md`, así que +`E14`; ⚠️ **sigue sin entrada en su registro**, ver `A43` en el registro de avisos del edge, así que esta cita no se puede calificar todavía— contra la captura de un **hub**, y la decisión salía mal cuatro veces seguidas. **No estaba mal: se estaba midiendo con la vara de otra sección.** ⇒ **Regla**: antes de objetar, pregúntate **de qué apartado es la decisión**. Si tu objeción vive en @@ -139,7 +139,7 @@ ser un invariante verificado.)* ⛔ **Una partición se verifica por SUS DOS CARAS: lo que debe estar cerrado Y lo que debe estar abierto.** Comprobar solo la mitad cerrada **no distingue «bien particionado» de «todo roto»** — y en autorización eso es peligrosísimo, porque el fallo se disfraza del resultado bueno. *(Cicatriz -2026-07-27: `athena-hub` daba **401 en toda la administración** y parecía protegida. **No lo estaba: +2026-07-27: un segundo hub daba **401 en toda la administración** y parecía protegida. **No lo estaba: estaba rota.** Su Ingress reclamaba `/api`, que una imagen pre-F1 no sirve, así que el catch-all autenticado se tragaba también **`/links/pair`** — el mismo accidente que cerraba `/admin/pair` impedía que **ningún device pudiera emparejarse**. Se vio al medir la cara abierta: `/links/pair` @@ -153,7 +153,7 @@ MÉTODO además de por ruta.** El guard corre **antes** de enrutar, así que no el enrutador —el panel usa `/`, `/pending`, `/devices/…`; la API `/links/*`— y era cierto **para el enrutador y falso para el guard**: `POST /devices/enroll` **casa con la plantilla** `GET /devices/{device_id}`, que es una página del panel. Una lista pública por **prefijo** habría -abierto esa página a internet — el accidente de athena, en espejo: allí el catch-all cerró de más, +abierto esa página a internet — el accidente del otro hub, en espejo: allí el catch-all cerró de más, aquí habría abierto de más.)* ⇒ La lista de lo público se genera **del montaje real**, nunca de un razonamiento sobre qué prefijos «son de la API»; y `GET /x` y `POST /x` son **dos entradas distintas**. @@ -194,7 +194,7 @@ usuario**, o seguirán certificando la copia equivocada. - 🔎 **Y para separar tu propio ruido del tráfico real, genera un evento conocido y búscalo.** En esa misma sesión, la pista fácil era falsa: los hits «sospechosos» salían de la **misma IP - pública y el mismo `curl`** que los del device (el Brume y el PC salen por el mismo NAT), así que + pública y el mismo `curl`** que los del device (el router de campo y el PC salen por el mismo NAT), así que *«curl = humano»* no valía. Lo que los separó fue lanzar un `curl` propio, ver **qué versión de User-Agent** aparecía, y comprobar que el llamador periódico casaba **exactamente** con el intervalo de descubrimiento del edge. @@ -209,7 +209,7 @@ a `src/api/tests/` y en `doc/` quedó un puntero.)* imagen?** Y su gemela, que es la buena noticia: **un gate que revienta porque le falta su insumo está funcionando** — el fallo silencioso habría sido que lo encontrara vacío y siguiera. -**Corolario (de Solidaria): el verde lo certifica el GATE/la medida, no tu palabra.** "Los tests +**Corolario: el verde lo certifica el GATE/la medida, no tu palabra.** "Los tests pasan" no es tu afirmación, es lo que dice el gate — y **antes de que exista artefacto** (gate rojo = no hay imagen que desplegar). Vale igual para cualquier "está hecho": lo certifica una comprobación, no la confianza en que lo hiciste bien. @@ -226,9 +226,9 @@ veredicto **distinto** de «comprobado y verde» (y no admisible por defecto en que **autentica** antes de `ready`. Pregunta única para cada señal: *«¿QUÉ tendría que estar roto para que esto se pusiera rojo, y ese estado PUEDE ocurrir de verdad?»* Si la respuesta es «no puede», es una tautología. *(Cicatriz 2026-07-28, barrido de la colección MCP: la MISMA clase apareció en los -CUATRO — la rotación de mcp-secrets daba verde por una señal pegajosa + `kv_exists` [el path ya -existía]; el `version_matches` de mcp-edge comparaba el `.ipk` con su propio `control`; el -`mint_token(git)` no probaba que el token AUTENTICARA; el `verified-ok` de mcp-build daba verde con +CUATRO — la rotación del MCP de secretos daba verde por una señal pegajosa + `kv_exists` [el path ya +existía]; el `version_matches` del MCP del edge comparaba el `.ipk` con su propio `control`; el +`mint_token(git)` no probaba que el token AUTENTICARA; el `verified-ok` del MCP de build daba verde con los pods VIEJOS sirviendo `200`; su gate A3 admitía `ungated` por ausencia de gates. Dos se cazaron por casualidad mirando otra cosa; el barrido encontró el resto. Dos de cuatro habría sido casualidad; cuatro de cuatro es un raíl.)* @@ -246,7 +246,7 @@ que consume tu salida **no aparece en tu `grep`**: se mide, o se mide. desempata.** *(Cicatriz Fase 14, 2026-07-28: `transport-spec.md` daba la derivación v2 de la loopback por «congelado ⏳» y describía la v1 —«la teclea el operador; el hub la asigna por `peer_index`»— con las **dos mitades falsas**. Su espejo decía lo mismo, así que **leyendo docs era -indetectable**: solo el hardware llevaba la contraria, con `10.100.203.26` en el Brume y +indetectable**: solo el hardware llevaba la contraria, con `10.100.203.26` en el router de campo y `10.100.255.154` en el hub. De la misma tirada cayó un problema que **la spec inventaba**: el puerto WG no es «443 RUTOS / 51820 OpenWrt» sino `51234` de escucha en ambas, así que el conflicto de despliegues mixtos que describía **no existe**.)* @@ -265,7 +265,7 @@ sobre una cadena que también aparece en el comando que la busca. ⛔ **Un testigo que no puede ponerse ROJO no es un testigo — y el que se pone rojo SIEMPRE mata lo que venía a proteger.** Si la señal que esperas la produce una capa **DELANTE** de lo que verificas, no está mirando tu sistema: está mirando al portero. *(Cicatriz `engine`, 2026-07-30, cazada **antes -de armarla**: el `verify` de mcp-build sale por internet y el Ingress de `engine` tiene whitelist de +de armarla**: el `verify` del MCP de build sale por internet y el Ingress de `engine` tiene whitelist de IP ⇒ devuelve **403 pase lo que pase**. Un `expect_status:200` habría fallado **siempre** → auto- rollback → re-pin del digest anterior, que daba **404** → `engine` muerto y sin vuelta atrás: el mecanismo de seguridad era el asesino. Y `expect_status:403` es **peor**: el ingress-controller @@ -275,14 +275,14 @@ firewall o el balanceador, cámbialo por uno que solo pueda salir **de dentro**. alcanzable, la respuesta correcta es **la palabra degradada** (`deployed-unverified`) más una comprobación a mano — no un `verify` decorativo, que es un rollback automático esperando su turno. ⇒ **Y el espejo: un testigo que se pone rojo SIN causa enseña a no creérselo.** *(Cicatriz -2026-07-31: `mcp-edge` dio `failed` sin que nada estuviera roto — su smoke midió durante el hueco de +2026-07-31: el MCP del edge dio `failed` sin que nada estuviera roto — su smoke midió durante el hueco de `uhttpd`.)* Falla hacia el lado seguro, sí, pero **un rojo que hay que desmentir a mano entrena a ignorar los rojos**, y el siguiente será de verdad. Un sondeo que puede caer en un hueco conocido **reintenta durante una ventana**; no informa del primer intento. ⛔ **Cuando una sonda te engaña, el arreglo es OTRO OBSERVABLE — no más reintentos.** Reintentar sobre un valor que el propio sujeto escribe solo es **esperar a que la tautología se complete**. -*(Cicatriz `A16`, 2026-08-01: `mcp-edge` leía la versión con `head -1` —**por posición**— y +*(Cicatriz `A16`, 2026-08-01: el MCP del edge leía la versión con `head -1` —**por posición**— y `/api/settings` tenía **dos claves `version`**; se quedaba con la del **install-report, un fichero que escribe el `postinst` del propio `.ipk`**. Resultado: `installed 2.1.58 · served 2.1.58 · HTTP 200 · 4/4 enabled`, **verde entero, con el panel ejecutando 2.1.57**. El arreglo no fue reintentar: fue @@ -501,7 +501,7 @@ mismo valor da el nombre público **y** direcciona secretos, rutas o etiquetas, visible **re-direcciona lo invisible**, y en silencio. *(Cicatriz 2026-07-31, cazada antes de aplicar: `hubName` gobernaba también los **paths de Vault** — con `hermes.hub` el `trimSuffix "-hub"` no recortaba nada y el hub habría ido a buscar su clave WireGuard y su **clave Rosenpass** —la que -`hermes-hub`·`D100` prohíbe regenerar; era `F13·D10` hasta que el 2026-08-22 se renumeró al +la `D100` del hub prohíbe regenerar; era `F13·D10` hasta que el 2026-08-22 se renumeró al contador del hub, precisamente porque el id chocaba con el del edge— a rutas inexistentes. La sesión partió **identidad** de **nombre público** antes de tocar nada.)* ⇒ Antes de renombrar, **escribe qué se deriva de ese valor**. Lo que dice quién eres y lo que dice @@ -512,7 +512,7 @@ probado que falla, no supuesto. ⛔ **Un comentario que JUSTIFICA saltarse una puerta sobrevive al motivo, y convierte el bypass en rutina.** Es el peor sitio donde se puede pudrir una nota: el resto de la documentación rancia hace perder el tiempo; ésta **desarma un gate y encima explica por qué está bien**. *(Cicatriz 2026-07-30: -el catálogo de `mcp-build` en asgard llevaba un CAVEAT diciendo que la suite de `hermes-hub` estaba +el catálogo del MCP de build llevaba un CAVEAT diciendo que la suite del hub estaba obsoleta —12/28 en rojo— y que por eso «el deploy se valida con `skip_tests`, bypass **auditado**». Había dejado de ser cierto el **2026-07-24**: las 12 aserciones se reescribieron y la suite va a **90 passed**. Seis días en los que la razón ya no existía y el permiso seguía escrito.)* @@ -541,7 +541,7 @@ que un día gestionó.** Dos caras, las dos medidas el 2026-07-30 desmontando ka credencial de escritura corriendo **sin dueño ni en git ni en ArgoCD**. Borrar es un `delete` explícito **después** del commit; el commit solo retira la gestión. - **Un fichero que la Application no incluye no existe para ArgoCD.** El appset de velero monta su - directorio con `directory.include: "externalsecrets.yaml"` ⇒ `velero-valhalla` salía + directorio con `directory.include: "externalsecrets.yaml"` ⇒ la Application de backup de un cluster salía **`Synced/Healthy` sin haber mirado nunca los `Schedule`**. Quitar un namespace del YAML en git no quitó nada: el objeto vivo seguía respaldándolo. @@ -669,7 +669,7 @@ no sólo *cómo* se parsea. ⛔ **Cuando un cambio de configuración pretende cambiar un COMPORTAMIENTO, el testigo es el ARTEFACTO GENERADO: guardado ANTES, comparado DESPUÉS, y el veredicto es su `diff` por caso.** **Un caso cuyo diff sale vacío no está construido, aunque no dé error: es un campo-señuelo.** -*(Cicatriz infraserver, cosecha 2026-08-15: `day1.mode` — dos modos producían **el mismo +*(Cicatriz del motor de aprovisionamiento, cosecha 2026-08-15: `day1.mode` — dos modos producían **el mismo artefacto**; y así llegó `day0.luks` a existir declarado y sin consumir, sin que nada se pusiera rojo.)* ⇒ Es el testigo independiente de §1 aplicado a la configuración: sin el artefacto de antes, «cambié @@ -682,7 +682,7 @@ la suite sale verde sobre un cableado roto. Dos veces en la misma semana (2026-0 asignar**, así que el peldaño de identidad llegaba **vacío**. Los tests pasaban **porque le pasan `cfg` a mano**. - Un mutante que derivaba el sufijo de una LAN del dominio del router —la invención que `F11·D8` - de `hermes-edge` prohíbe— **no rompió ni una aserción**, porque sus tests **no pasaban registro + del edge prohíbe— **no rompió ni una aserción**, porque sus tests **no pasaban registro de router**. ⇒ Pregunta por cada test que pasa: **¿de dónde sale ese argumento en producción?** Si lo fabrica el test, ahí no hay cobertura — hay una simulación de que la hay. El testigo tiene que **entrar por @@ -811,7 +811,7 @@ Tests verdes ≠ funciona. Conduce el flujo de punta a punta en el medio real. - El «Editar» de la br-lan llevaba **roto desde F9.2** (promesa muerta en silencio); sin abrir el navegador, F11.0/F11.1 se habrían dado por buenas siendo **inaccesibles**. -- El PSK PQ, el `.ipk`, el DNS: validados en el Brume real, no en mock. +- El PSK PQ, el `.ipk`, el DNS: validados en el router de campo real, no en mock. ⛔ **Sondear una escritura ES escribir.** Un cuerpo malformado **no** es una sonda segura: una API cuyos campos son todos opcionales lo acepta encantada como *«pon todo por defecto»*. *(Cicatriz @@ -857,9 +857,9 @@ El plan escrito puede partir de una foto obsoleta o de otro entorno. - F10.3 en FRR: el hub tiene **cero rutas OSPF en la FIB** (las conectadas ganan) → la fuente es la RIB de FRR, no `ip route`. Copiar el filtro del edge habría dado tabla vacía con todo OK. -- Los puertos del `br-lan` no salen de `network.br_lan.ports` (el Brume usa sección UCI +- Los puertos del `br-lan` no salen de `network.br_lan.ports` (ese router usa sección UCI **anónima**) → se miden del kernel (`brif`). -- Higiene de git de asgard: la premisa ("la doc no está en el remoto") era **falsa**; un rebase +- Higiene de git del repo de GitOps: la premisa ("la doc no está en el remoto") era **falsa**; un rebase literal habría degradado doc buena. Verifica antes de reescribir. **Una decisión ya cerrada en la ficha es una premisa: contradecirla es PARAR y reportar, nunca @@ -903,7 +903,7 @@ al segundo intento**.)* Antes de convertir un fallo en una conclusión: **reinte fallar, reporta el error **literal** en vez de tu interpretación de él — «connection reset» y «no autorizado» no son lo mismo y llevan a sitios opuestos. -**Y (de Solidaria) si una premisa del encargo es falsa: PARA y repórtalo — no la "arregles" sobre la +**Y si una premisa del encargo es falsa: PARA y repórtalo — no la "arregles" sobre la marcha.** El prompt puede dar por hecho algo que no se sostiene; corregirlo en silencio esconde el problema. Además: **lo que verificaste en una sesión anterior PUEDE haber cambiado** (otras sesiones, otros commits entre medias) → de lo heredado tienes MÁS que re-verificar, no menos, justo porque @@ -939,7 +939,7 @@ cadena única) en vez de por número de línea; los números se recalculan solos Un artefacto compartido vive en **un** sitio; los consumidores llevan copia **commiteada** (build sin red/Node) y un `--check` detecta la deriva. Nunca se edita la copia. -- `manabo-ui` (design system propio) → `sync.sh` copia y `--check` verifica; el `.ipk` y la +- El design system propio → `sync.sh` copia y `--check` verifica; el `.ipk` y la imagen del hub construyen sin dependencias externas. Tres consumidores, cero cambios en el componente = el contrato estaba bien puesto. @@ -1003,7 +1003,7 @@ sesión de diseño mira ahí **qué contradice** antes de cerrar nada, y si cont ⛔ **Un valor por DEFECTO declarado como dato en la capa base solo es fuente única si TODOS los consumidores pasan por el merge.** El que se lo salta no es un descuido: es una **segunda fuente** —con su propia verdad— y hay que buscarlo **explícitamente al introducir el default**, no el día que -los dos valores diverjan. *(Cicatriz infraserver, cosecha 2026-08-15: un endpoint construía su vista +los dos valores diverjan. *(Cicatriz del motor de aprovisionamiento, cosecha 2026-08-15: un endpoint construía su vista **sin mergear la capa base** y devolvía otro valor.)* ⇒ Es la pregunta de la poda (§1) en la capa de datos: **¿quién MÁS lee esto, y por dónde?** Declarar el default no reparte el default. @@ -1124,7 +1124,7 @@ que el remedio quita lo que venía a proteger. alternativo no se ve mientras el camino alternativo esté — y aparece **exactamente** el día que ya no está, o sea en el peor momento y sin historial. *(Cicatriz `A18`, 2026-07-31: con la identidad del edge divergiendo entre los dos hubs, el nombre **seguía respondiendo 3/3** porque el tráfico rodeaba -por el otro Brume —`G8` funde los dominios de inundación—. Con ese aparato apagado, el hub habría +por el otro router de campo —`G8` funde los dominios de inundación—. Con ese aparato apagado, el hub habría perdido al edge **del todo**.)* ⇒ Para ver el fallo, **quita la redundancia y vuelve a medir**: apaga el camino alterno, tira el segundo hub, desconecta el vecino. Un verde obtenido con todas las rutas vivas **no dice si el @@ -1134,7 +1134,7 @@ servicio funciona: dice que alguna de ellas funciona.** siempre en el aparato más holgado no certifica nada del más apretado — y el defecto no está latente, está **ocurriendo**, solo que sobra sitio para pagarlo. *(Cicatriz `P12`, 2026-08-02: con `F13·D10` —la del **edge**, «PQ siempre que se pueda»— un edge **sin binario de Rosenpass** seguía bajándose -la pubkey del hub —**524.160 B**— en el bucle de 20 s **y por cada hub**. En un Brume 2 (6,8 GB de +la pubkey del hub —**524.160 B**— en el bucle de 20 s **y por cada hub**. En el router grande (6,8 GB de overlay) no se nota **jamás**; en un GL-AR300M eran **1 MB sobre 212 KB libres**. Se descubrió porque el aparato pequeño lo hizo visible, no porque alguien lo buscara.)* ⇒ Pregunta cuando una medida salga limpia: **¿en qué aparato la he tomado, y qué le sobraba?** Disco, @@ -1158,7 +1158,7 @@ una limpieza en una pérdida. ⇒ **Y el mismo raíl al revés: un arreglo COMMITEADO no es un arreglo APLICADO.** Todo lo que se lee **al arrancar** —ConfigMap, variables de entorno, fichero de configuración— sigue siendo el viejo hasta que el proceso reinicie, y el `git log` dice que está arreglado. *(Cicatriz 2026-07-31: -`mcp-build` llevaba **21 h** con el config anterior al renombrado de los hubs. El fix se commiteó a +el MCP de build llevaba **21 h** con el config anterior al renombrado de los hubs. El fix se commiteó a las 00:49, pero **editar un ConfigMap no rueda el Deployment** ⇒ seguía sondeando un nombre que hoy es `NXDOMAIN` ⇒ el `verify` no respondía nunca ⇒ **auto-rollback que deshizo un pin bueno**. Tercera vez esta semana que **el mecanismo de seguridad es el asesino**.)* @@ -1215,14 +1215,14 @@ internet.)* ⇒ En las plantillas, `required` en todo valor cuyo vacío sea peli de **preferencia** —qué valor usar entre varios válidos— es legítimo. Un default de **identidad** —qué ES esto— **no existe**: si el dato que identifica al artefacto no está declarado, el artefacto **no se puede construir**, y la respuesta es un fallo explícito **con su motivo**, nunca el valor más -común. *(Cicatriz infraserver, cosecha 2026-08-15: un hueco de identidad rellenado con «lo de +común. *(Cicatriz del motor de aprovisionamiento, cosecha 2026-08-15: un hueco de identidad rellenado con «lo de siempre» sirvió un **kickstart destructivo** con un **HTTP 200** impecable.)* ⛔ **Y el corolario que este raíl NO llevaba, medido seis veces el 2026-08-19: un fallo benigno explícito sólo protege si alguien LEE la línea.** Un banco que se salta algo **anunciándolo**, en una salida que nadie mira, produce el mismo resultado que el silencio — y encima con la conciencia tranquila de haberlo declarado. *(Cicatriz `V11b`: el careo `routes-*.txt` ↔ `superficie.md` del -chart del hub buscaba `repos/infrarouter/…`, carpeta renombrada a `repos/hermes-hub` el +chart del hub buscaba `repos/infrarouter/…`, carpeta renombrada la 2026-08-15. Se saltó en **todas** las corridas de cuatro días, y no en silencio: llevaba un `warnings.warn` **además** del `pytest.skip`, puesto a propósito citando este §8, con el comentario «*esto no se salta en silencio — se salta diciéndolo*». **Y lo decía. Y nadie lo leyó.** Mientras @@ -1233,9 +1233,9 @@ número mueva el **código de salida**, no la pantalla. Las tres formas que ya e se copian en vez de inventarse: - **suelo de comprobaciones EJECUTADAS** (`guards.sh`: `SUELO_CHECKS`) — un `command not found` no para el script y la comprobación *simplemente no ocurre*; -- **suelo de mutaciones EJECUTADAS** (los bancos de `hermes-edge`/`hermes-hub`) — una mutación que +- **suelo de mutaciones EJECUTADAS** (los bancos del edge y del hub) — una mutación que deja de casar **no se queja**; -- **un `skip`/una dormancia CONTADOS** (`helm-charts/hermes-hub/tests/conftest.py`) — saltarse un +- **un `skip`/una dormancia CONTADOS** (el `conftest.py` del chart del hub) — saltarse un careo es rojo, y las ausencias legítimas se declaran **por nombre** y se carean **por igualdad**, para que la lista no se pudra afirmando una ausencia que ya no existe. @@ -1340,7 +1340,7 @@ el canal, o el relevo sólo ha movido la deuda de sitio.** ⛔ **El ESTADO DE OTRO FRENTE se re-verifica antes de retransmitirlo — o se marca «según me dijeron a las HH:MM».** Nunca se afirma en plano. *(Cicatriz 2026-08-28, y son **cuatro** el mismo día, en -tres frentes: «`E2.1` está bloqueado esperando `jon`» —falso—; «esas dos filas son de sesiones +tres frentes: «`E2.1` está bloqueado esperando un hierro prestado» —falso—; «esas dos filas son de sesiones muertas» —una era de una sesión **viva y escribiendo en ella**—; «tiene 5 commits sin empujar» —ya estaban empujados—; y una alarma de hierro que **movió el orden de la cola del usuario**. **Los cuatro iban en el bloque afirmativo, ninguno marcado como inferencia.**)* @@ -1413,7 +1413,7 @@ cosas nuevas a la vez. - "Nunca borres el `IPAddressPool` viejo hasta tener el nuevo sirviendo" (MetalLB). - El cutover de un servicio con nombre: primero responde el nuevo, luego se retira el viejo. -## 12. Exploración solo-lectura, sin autoengaño · *C35 (Solidaria), promovido 2026-08-08* +## 12. Exploración solo-lectura, sin autoengaño · *C35, promovido 2026-08-08* Explorar es **medir sin tocar, y sin creerte tu propia medida**. @@ -1423,7 +1423,7 @@ Explorar es **medir sin tocar, y sin creerte tu propia medida**. (un patrón demasiado amplio), no el sistema. Verifica cada hit contra la fuente antes de declararlo. - Sobre **texto generado**, el testigo se define sobre las líneas **EJECUTABLES**, no sobre el fichero: si el generador emite comentarios que documentan las ramas NO tomadas, el grep ingenuo - mide el comentario — verde indistinguible de rojo. *(Cicatriz: banco de render de infraserver, + mide el comentario — verde indistinguible de rojo. *(Cicatriz: banco de render del motor, 2026-08-12.)* - Medir, no opinar. Sondear una escritura **ES** escribir (no es exploración).