diff --git a/.metodo/CHECKSUMS b/.metodo/CHECKSUMS index b2b090c..e6244de 100644 --- a/.metodo/CHECKSUMS +++ b/.metodo/CHECKSUMS @@ -1,7 +1,7 @@ -4ee74ad69f1adceab2a56d3814bf96d9bbc3a42b285795c339585d3bf51a616e metodo.md -17d070adba8cf56a50df6cd50e681d1b8f391c9b9b1a6eff16812322f36a1a22 bin/metodo +343e8a8b741931d28a9aa09a1f4cc3b7e92f20e825fe49d511bde3e3641ca22c metodo.md +7a8d29ab793674397b50489a01825e469b52593a12bc24c4368bcfc469d20559 bin/metodo f89b71bdf31028b05075636c1763c964e379bc37a00e0357d1c23a4dd19c09aa workflows/README.md cc241bbecf9647c747b8525b3a6b527455cd50ca0312caa44bc3544342c8ac41 workflows/comunicacion-entre-sesiones.md 2b9037f6dd57b5598c70a676cb728556654f05d1c5b024e7b716864659f7b884 workflows/sesion-ejecucion.md f35dda490674d37da4a8f9412a2463ea37c42c02af4f63d642e06c8a3f9cfc90 workflows/sesion-exploracion.md -36e46215a205d78c4ce99896d1c163634e9a72993db58c6e41f92f4792b791e1 workflows/sesion-orquestadora.md +b96e9bba7363e58361c797839a6cad443575b6c74efe66b8bc046b60f76b8a17 workflows/sesion-orquestadora.md diff --git a/.metodo/bin/metodo b/.metodo/bin/metodo index ffdd07b..61a9121 100644 --- a/.metodo/bin/metodo +++ b/.metodo/bin/metodo @@ -84,6 +84,24 @@ info() { printf ' \033[36minfo\033[0m %s\n' "$*"; } # censo, NO veredicto: no # porque el glob `workflows/*.md` no recursa — una protección implícita, o sea algo que # funciona por casualidad. Si alguien cambia ese glob, los apéndices empiezan a viajar a # 27 repos en silencio. Este check lo dice. +# ⛔ Gate del semáforo (2026-08-30). Es DECIDIBLE SIN ADIVINAR —está el marcador o no está— +# y por eso se ata. Su hermana, «ninguna sesión se cierra con fila viva», NO se ata a +# propósito: el fichero no puede saber si el dueño respira, y un gate que lo adivinara daría +# rojos crónicos, que es la ceguera que este mismo Método prohíbe. Queda como criterio +# humano, y se dice — o alguien lo mecanizará «por completitud» y creará el rojo permanente. +check_semaforo_en_vuelo() { + local f="$ROOT/workflows/sesiones-activas.md" + [ -f "$f" ] || return 0 # sólo aplica donde vive el semáforo (el árbol) + hdr "filas vivas con bloque EN VUELO" + local vivas sin + vivas=$(grep -c "^| 2026.*🟢" "$f" 2>/dev/null || echo 0) + sin=$(grep "^| 2026.*🟢" "$f" 2>/dev/null | grep -vc "EN VUELO" || echo 0) + if [ "$sin" -gt 0 ]; then + bad "$sin de $vivas fila(s) 🟢 sin bloque EN VUELO — una fila viva sin estado en vuelo no releva a nadie" + else + ok "$vivas fila(s) 🟢, todas con EN VUELO" + fi +} check_apendices_no_viajan() { hdr "los apéndices NO viajan (son de proyecto, no de método)" local d="$ROOT/.metodo/workflows/apendices" n @@ -369,7 +387,7 @@ check_commits() { local excf="$ROOT/.metodo/EXCEPCIONES" exc_c=0 sha subj while IFS=$'\t' read -r sha subj; do [ -n "$sha" ] || continue - printf '%s' "$subj" | grep -qE '^(feat|fix|docs|ci|refactor|test|chore|build|perf|semaforo|semáforo|avisos|bitacora|bitácora|decisiones|backlog|corpus|evidencia|banco|fix|docs|ci|refactor|test|chore|build|perf|semaforo|semáforo)(\(.+\))?!?: .' && continue + printf '%s' "$subj" | grep -qE '^(feat|fix|docs|ci|refactor|test|chore|build|perf|deploy|doc|semaforo|semáforo|avisos|semaforo|semáforo|avisos|bitacora|bitácora|decisiones|backlog|corpus|evidencia|banco|fix|docs|ci|refactor|test|chore|build|perf|semaforo|semáforo)(\(.+\))?!?: .' && continue if [ -f "$excf" ] && grep -qE "^C25[[:space:]]+${sha}([[:space:]]|$)" "$excf"; then exc_c=$((exc_c+1)); continue fi @@ -908,6 +926,7 @@ cmd_check() { printf 'metodo check — %s\n' "$ROOT" check_drift check_apendices_no_viajan + check_semaforo_en_vuelo check_ids check_headings check_links diff --git a/.metodo/metodo.md b/.metodo/metodo.md index ebb793c..156005d 100644 --- a/.metodo/metodo.md +++ b/.metodo/metodo.md @@ -877,6 +877,18 @@ enseñaba una capa contra una decisión del usuario, y cede el sujeto. Se arregl avisa. El que lo reportó se queda con su aviso abierto, persiguiendo lo que ya estaba resuelto.)* ⇒ La entrega termina en **el que reportó**, no en el `push`. + +**(c) UN AVISO QUE SE REPITE EN UN RELEVO SE RE-MIDE, NO SE REENVÍA.** El relevo es **justo el momento +en que el estado cambió y quien informa no estaba delante**: entre que avisaste y llega el sucesor, +alguien pudo arreglarlo. Reenviar el aviso viejo **manda a la nueva a perseguir algo ya hecho** —y +peor, **con la autoridad de venir de quien lo descubrió**. +*(Cicatriz 2026-08-30, **dos veces el mismo día y en direcciones opuestas**: un frente avisa al relevo +de que cierta decisión seguía apoyada en una premisa falsa… **y ya estaba corregida y sustituida**, +por él mismo, la víspera. Y la superadmin repite ese mismo aviso al día siguiente **sin volver a +mirar**. Las dos veces lo cazó la sesión nueva, que era la única que **no daba el estado por sabido**.)* +⇒ ⭐ **Y las tres de este bloque son la misma familia con el fallo movido de sitio**: **(a)** falla +**a quién** · **(b)** falla **que no se dijo** · **(c)** falla **cuándo**. En las tres **el dato es +correcto** — lo que está mal es **a quién, o desde cuándo, se refiere**. ⭐ **La familia, que es lo que hace que se retengan las dos**: son primas de las cicatrices del instrumento sin sujeto —el log sin *quién*, el `uptime` sin *cuándo*, el `push` sin *de quién*—, pero **con el sujeto movido de sitio**. Allí el dato no decía de qué hablaba; aquí **el dato es correcto y @@ -1628,9 +1640,32 @@ pega tal cual. ilegible por costumbre, y (c) ésta: **enrojece bien y no ata nada**. ⇒ **Un gate sólo ata si rompe el flujo por sí mismo** —código de salida, comando que no continúa—, nunca delegando el veredicto en quien lo lee. + ⛔⛔ **CUARTA CARA, y es la que más engaña: UNA PUERTA CUYO RESULTADO SE LEE DESPUÉS DE ACTUAR NO ES + UNA PUERTA — ES UN REGISTRO DE LO QUE YA PASÓ.** Aquí el gate **calcula bien, enrojece bien y el + operador lo lee**… y no sirve, porque **no hubo ningún instante en el que pudiera parar**. + *(Cicatriz 2026-08-30, y con la puerta puesta: una sesión encadena la comprobación y el + `git commit` **en la misma orden**. Sale `4 filas tocadas · 2 de 4 mías` —debía parar— pero para + cuando lee la salida **el commit ya está hecho**, y publica el bloque a medio escribir de otra + sesión bajo un mensaje que hablaba de otra cosa.)* + ⇒ **La forma no es «correr la puerta»: es que la ACCIÓN sea un paso DISTINTO Y POSTERIOR a leerla.** + Un `&&` entre la comprobación y el acto **convierte el gate en telemetría**. Si van en la misma + orden, la comprobación **tiene que abortar ella misma** (cara *(c)*) — leerla no basta. ⇒ Y el criterio para saber cuál estás escribiendo, que es de la sesión que lo pagó: **si el cumplimiento depende de la atención de quien tiene prisa, no has escrito un raíl: has escrito un consejo.** Un raíl se cumple **aunque no te acuerdes de él**. + ⇒ ⭐ **Y la regla NO es «átalo todo»: es ÁTALO SI ES DECIDIBLE SIN ADIVINAR — y si no lo es, DI POR + QUÉ NO LO HAS ATADO.** Un raíl que explica **por qué no se mecaniza** es lo único que impide que el + siguiente lo mecanice mal *«por completitud»*. + *(Caso 2026-08-30, dos prescripciones hermanas y sólo una atable: **«una fila viva lleva bloque + `EN VUELO`»** es puramente sintáctico —está el marcador o no está—, así que **se ata** y pasa de + «acuérdate» a «no puedes empujar sin ponerlo». Su hermana, **«ninguna sesión se cierra con fila + viva»**, **NO se ata a propósito**: el fichero **no puede saber si el dueño respira** —medido: + `ListAgents` pasó de 13 sesiones a 6 en dos minutos, y una de 12 h apareció como recién + arrancada—, así que un gate que lo adivinara daría **rojos crónicos**, o sea la cara (b) de la + familia de arriba. Queda como **criterio humano, deliberadamente**.)* + ⛔ **Y por eso se escribe el NO**: una prescripción sin gate y sin explicación se lee como un + descuido, y el siguiente que pase «lo arreglará» — creando justo el rojo permanente que este + párrafo prohíbe. vez de `22/22`. **Un gate que se pone rojo por causa ajena entrena a desmentirlo**, así que cuando salga descuadrado la pregunta no es *«¿qué he hecho mal?»* sino **«¿de quién es lo demás?»** — y la respuesta es un mensaje, no un `commit`. diff --git a/.metodo/workflows/sesion-orquestadora.md b/.metodo/workflows/sesion-orquestadora.md index 6ca428d..400c85a 100644 --- a/.metodo/workflows/sesion-orquestadora.md +++ b/.metodo/workflows/sesion-orquestadora.md @@ -47,8 +47,34 @@ se tiene.** Todo momento tiene que ser un punto de relevo válido. **Qué lo hace posible, y es lo único que hay que cumplir:** 1. **Una decisión del usuario se escribe ANTES de actuar sobre ella.** No después, no «al cerrar». Es el único campo que un sucesor **no puede reconstruir de ningún sitio**, y el que más caro sale. -2. **Lo que está en vuelo vive fuera de la sesión** —qué debes, qué esperas, cuál es el hilo—, en el - sitio que tu árbol use para arbitrar sesiones concurrentes. Se **reescribe**, no crece. +2. **Lo que está EN VUELO vive fuera de la sesión.** Son **cuatro campos**, y son los cuatro que las + capas del corpus **no** guardan: + + EN VUELO () · debo: · espero: + · hilo: · sin escribir: + · gesto siguiente: + + - **debo** — lo que otro espera de ti y aún no has entregado. + - **espero** — de quién y qué. Si muere quien te lo debe, **esto es lo único que lo dice**. + - **hilo** — por qué haces justo esto. Es lo que un sucesor **no puede reconstruir del corpus**. + - ⭐ **sin escribir** — decisiones del usuario que aún **no están en `doc/`**. **Lo sano es + «nada»**; si tiene contenido, **es deuda y se paga antes que nada**. + - ⭐ **gesto siguiente** — **el comando o la acción física que toca**, o «ninguno». Medido: + *un sucesor no se atasca en una decisión difícil; se atasca en no saber si teclear un + comando o hacer `git push`.* Sin este campo, **«cerrada» y «cerrada pero falta empujar» + se leen igual**. *(Lo estrenó una orquestadora el día de estrenar el bloque.)* + + ⛔ **Se REESCRIBE, no crece**: es una foto, no un diario — el diario es la bitácora. Una línea + por campo. + ⇒ **Dónde vive lo pone tu árbol, no este fichero**: si trabajas en un árbol multi-repo, va en + **tu fila del semáforo** (`repos/metodo/workflows/sesiones-activas.md`, ruta del árbol) — + *(si has clonado este repo suelto, esa ruta no existe: entonces vive donde tu repo arbitre + sesiones concurrentes, y si nunca hay dos a la vez, en el sitio que leas al arrancar)*. + ⚠️ *(Esto se escribió el 2026-08-30 y **nació roto**: la mitad que **motiva** viajaba a los 27 + repos y la que **instrumenta** —los cuatro campos— se quedó en el semáforo, que **no viaja**. Lo + cazó una orquestadora **el día de estrenarlo**, haciendo `grep` en su `.metodo/` y saliendo + vacío. ⇒ **Una mitad que comprueba que algo esté y otra que sabe qué es, sin que nadie las + junte**, es la forma de defecto más repetida de este árbol.)* 3. **Lo demás ya tiene capa**: decisión → `decisiones.md` · trabajo → `backlog.md` · trampa → `AVISOS.md` · relato → `bitacora.md`. Si dudas de dónde va, **el sitio equivocado es tu cabeza**. @@ -74,6 +100,17 @@ antecesora, aunque no solapen**: para ellas eres su nuevo interlocutor y **no ti documentado siempre va por detrás de lo hecho ⇒ tenderá a leer **el último trabajo de su antecesora como ajeno**. Si algo del repo te parece una intrusión, **pide el crudo antes de decirlo** (`R9`). ⇒ El disparador concreto de cada frente está en su apéndice. + +⛔ **Y un límite del terreno que cambia lo que puedes reconstruir: en un árbol donde todas las +sesiones commitean con la MISMA identidad de máquina, «quién hizo este commit» es INCONTESTABLE +desde `git`.** Un `--author` devuelve **a todo el mundo**. ⇒ **Lo único que atribuye es el MENSAJE** +—y el semáforo—, así que un commit ajeno bajo un mensaje que habla de otra cosa **no es un detalle +estético: borra la única atribución que existe**. +⇒ Y para ti, que llegas de relevo: **no puedes saber qué dejó tu antecesora salvo por lo que digan +los mensajes.** Si un protocolo te dice *«mira qué hizo la anterior»*, eso **sólo funciona si los +mensajes lo cuentan**. *(Medido 2026-08-30 por una sesión que fue a auditarse y se encontró con los +commits de las demás. Se salvó **porque escribe mensajes largos con el porqué** — no porque `git` la +distinguiera.)* ## Cómo arranca una sesión orquestadora nueva Cuando la sesión actual se agota de contexto, hay que abrir una nueva que retome