Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions reference/core/control-center/gaps/gap-reference-catalog.es.md
Original file line number Diff line number Diff line change
Expand Up @@ -7855,6 +7855,20 @@ Serie histórica de gaps registrada en el antiguo `gap-analysis-core.es.md`, pre
- [x] El tipo `security` está declarado en la config de commitlint con un mapeo explícito de salto de versión, o se deja de usar.
- [x] Ningún hook de `.husky/` imprime un mensaje de "skipping" y sale con cero — un hook que no puede correr se borra, no se silencia.

#### GT-639

**Title:** Nada hace visible el trabajo en vuelo entre ramas, así que el mismo gap se arregla dos veces

- **Purpose:** Que un gap que ya se está trabajando sea descubrible ANTES de que una segunda sesión lo empiece, y no en el merge.
- **Evidence:** **El 2026-07-30 el mismo trabajo se hizo dos veces, en tres ocasiones distintas, por sesiones que no podían verse.** (1) [`GT-633`](./gap-reference-catalog.es.md#gt-633) se arregló dos veces: un script de captura aterrizó en `main` como #276 y un renderer independiente dentro del spec aterrizó en `develop` como #279. Los dos eran correctos, los dos recapturaron los mismos números — y dos generadores para un artefacto es el defecto del propio GT-633 un nivel más arriba, así que una TERCERA sesión gastó una reconciliación entera (#294, #295, #296, #297) en dejar un solo renderer. (2) El parser del guard de evidencias se arregló dos veces: `d1ea72a3` en `main` ("stop the evidence guard blaming the evidence for two parser defects") y `5acb29ed` en `develop` ("the ratchet was stuck by two bugs in itself"). (3) Un id de GT se asignó dos veces, forzando la renumeración que registra [`GT-638`](./gap-reference-catalog.es.md#gt-638). **El coste no es el conflicto de merge.** Es el trabajo duplicado que ocurrió antes de que nadie llegara al conflicto, más la reconciliación que hizo falta después — y esa reconciliación introdujo un defecto propio (una comparación sensible al orden que reescribía la fecha de captura en cada corrida, invisible durante un día porque ambas estampaban la misma fecha). Tres duplicaciones, una sesión de reparación y un bug nuevo: ésa es la factura real. **Por qué el tablero no lo ve hoy:** una fila lleva estado (`PENDIENTE`, `EN-PROGRESO`) pero no QUIÉN la trabaja ni DÓNDE. Dos sesiones pueden leer ambas `GT-633 · PENDIENTE` y empezar ambas, correctamente. `08-validate-tracking` valida dentro de un único árbol de trabajo por construcción, así que no puede saber que existe otra rama. **Esto no es una convención que falte — la convención existe.** La regla de un solo driver para las olas de gaps es práctica establecida; lo que falta es cualquier mecanismo que la haga observable, así que en un día cargado se degrada en silencio y nadie se entera hasta el merge. Direcciones de arreglo: exigir una reclamación (rama o PR) en la fila que pasa a `EN-PROGRESO`, y derivar el conjunto de reclamaciones de los PR abiertos para que no pueda quedarse rancio; después, fallar en PR cuando un id `GT-*` esté reclamado por más de una rama abierta, nombrando a las dos.
- **Component:** `Governance` · **Criticality:** P2 · **Complexity:** M
- **Provenance:** Registrado el 2026-07-30 a partir de tres instancias observadas en un solo día, todas en el merge `develop` → `main` que las hizo visibles. Relacionado pero distinto de [`GT-638`](./gap-reference-catalog.es.md#gt-638): aquella fila trata de asignar un NOMBRE dos veces, ésta de hacer el TRABAJO dos veces. La misma carencia de coordinación produce ambas, y la colisión de id es su síntoma más barato.
- **Acceptance criteria:**
- [ ] Un gap que se está trabajando es descubrible desde el tablero junto con la rama o el PR que lo reclama, antes de que el trabajo aterrice.
- [ ] Una comprobación falla en pull request cuando un id `GT-*` está reclamado por más de una rama abierta, nombrando a ambos reclamantes.
- [ ] La reclamación se DERIVA de los pull requests abiertos y no se escribe a mano, para que no pueda quedarse rancia en la dirección que importa.
- [ ] Incluye una fixture negativa OBSERVADA en rojo, no sólo declarada capaz de fallar.

#### GT-638

**Title:** El tablero no tiene asignador de ids, así que dos ramas paralelas reparten el mismo número GT
Expand Down
14 changes: 14 additions & 0 deletions reference/core/control-center/gaps/gap-reference-catalog.md
Original file line number Diff line number Diff line change
Expand Up @@ -7950,6 +7950,20 @@ Historical gap series tracked in the former `gap-analysis-core.md`, preserved fo
- [x] The `security` type is either declared in the commitlint config with an explicit version-bump mapping, or removed from use.
- [x] No hook in `.husky/` prints a "skipping" message and exits zero — a hook that cannot run is deleted, not silenced.

#### GT-639

**Title:** Nothing makes in-flight work visible across branches, so the same gap gets fixed twice

- **Purpose:** Make a gap that is already being worked discoverable BEFORE a second session starts it, rather than at merge time.
- **Evidence:** **On 2026-07-30 the same work was done twice, three separate times, by sessions that could not see each other.** (1) [`GT-633`](./gap-reference-catalog.md#gt-633) was fixed twice: a standalone capture script landed on `main` as #276, and an independent in-spec renderer landed on `develop` as #279. Both were correct, both recaptured the same numbers — and two generators for one artifact is GT-633's own defect one level up, so a THIRD session spent a full reconciliation (#294, #295, #296, #297) collapsing them to one renderer. (2) The evidence guard's parser was fixed twice: `d1ea72a3` on `main` ("stop the evidence guard blaming the evidence for two parser defects") and `5acb29ed` on `develop` ("the ratchet was stuck by two bugs in itself"). (3) A GT id was allocated twice, forcing the renumber recorded in [`GT-638`](./gap-reference-catalog.md#gt-638). **The cost is not the merge conflict.** It is the duplicated work that happened before anyone reached the conflict, plus the reconciliation it then required — and that reconciliation introduced a defect of its own (an order-sensitive comparison that rewrote the capture date on every run, invisible for a day because both runs stamped the same date). Three duplications, one repair session, one new bug: that is the real bill. **Why the board cannot see it today:** a row carries a status (`PENDING`, `IN-PROGRESS`) but not WHO is working it or WHERE. Two sessions can both read `GT-633 · PENDING` and both start, correctly. `08-validate-tracking` validates within one working tree by construction, so it cannot know another branch exists. **This is not a missing convention — the convention exists.** The single-driver rule for gap waves is already established practice; what is missing is any mechanism that makes it observable, so on a busy day it degrades silently and nobody learns until the merge. Fix directions: require a claim (branch or PR) on a row that moves to `IN-PROGRESS`, and derive the claim set from open PRs so it cannot go stale; then fail at PR time when one GT id is claimed by more than one open branch, naming both.
- **Component:** `Governance` · **Criticality:** P2 · **Complexity:** M
- **Provenance:** Registered 2026-07-30 from three observed instances in a single day, all of them in the `develop` → `main` merge that made them visible. Related but distinct from [`GT-638`](./gap-reference-catalog.md#gt-638): that row is about allocating a NAME twice, this one about doing the WORK twice. The same coordination gap produces both, and the id collision is the cheapest symptom of it.
- **Acceptance criteria:**
- [ ] A gap being worked is discoverable from the board together with the branch or PR that claims it, before the work lands.
- [ ] A check fails at pull-request time when one `GT-*` id is claimed by more than one open branch, naming both claimants.
- [ ] The claim is DERIVED from open pull requests rather than hand-written, so it cannot be stale in the direction that matters.
- [ ] It ships with a negative fixture that has been OBSERVED red, not merely declared able to fail.

#### GT-638

**Title:** The board has no id allocator, so two parallel branches hand out the same GT number
Expand Down
3 changes: 2 additions & 1 deletion reference/core/control-center/gaps/gap-tracking.es.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ Este tablero es la única fuente de verdad para deuda técnica, gaps, oportunida

| ID | Gap | Qué significa | Ejemplo | Componente | Fase | Criticidad | Complejidad | Estado |
|---|---|---|---|:---:|:---:|:---:|:---:|:---:|
| [`GT-639`](./gap-reference-catalog.es.md#gt-639) | **Nada hace visible el trabajo en vuelo entre ramas, así que el mismo gap se arregla dos veces.** El 2026-07-30 el mismo trabajo se hizo dos veces, en tres ocasiones distintas, por sesiones que no podían verse: [`GT-633`](./gap-reference-catalog.es.md#gt-633) arreglado por un script de captura en `main` (#276) Y por un renderer independiente dentro del spec en `develop` (#279) — los dos correctos, los dos recapturando los mismos números, y dos generadores para un artefacto es el defecto del propio GT-633 un nivel más arriba, así que una tercera sesión gastó una reconciliación entera en dejar uno; el parser del guard de evidencias arreglado dos veces (`d1ea72a3` en main, `5acb29ed` en develop); y un id de GT asignado dos veces, forzando la renumeración que hay detrás de [`GT-638`](./gap-reference-catalog.es.md#gt-638). **El coste no es el conflicto de merge** — es el trabajo duplicado antes de que nadie llegara a él, más la reconciliación, que introdujo un defecto propio (una comparación sensible al orden que reescribía la fecha de captura en cada corrida, invisible un día porque ambas estampaban la misma fecha). Una fila lleva estado pero no QUIÉN la trabaja ni DÓNDE, así que dos sesiones pueden leer ambas `PENDIENTE` y empezar ambas, correctamente. **La convención de un solo driver ya existe; lo que falta es un mecanismo que la haga observable**, así que en un día cargado se degrada en silencio. | | | `Governance` | Cross | P2 | M | `PENDIENTE` |
| [`GT-638`](./gap-reference-catalog.es.md#gt-638) | **El tablero no tiene asignador de ids, así que dos ramas paralelas reparten el mismo número GT.** Un id se elige leyendo el `GT-*` más alto de la rama en la que uno está, y nada lo contrasta con otra rama — así que dos sesiones en paralelo asignan el mismo número y una se entera en el merge. Ya pasó: `8449af3d` en `develop` dice *"renumber the ratchet fix GT-634 -> GT-637, ID collision with develop"*; esa fila y [`GT-634`](./gap-reference-catalog.es.md#gt-634) en `main` tomaron el mismo id con horas de diferencia, desde sesiones que no podían verse. **La renumeración es manual y con pérdidas**, que cuesta más que el choque: un id vive en la fila del tablero, el ancla del catálogo, el registro de evidencia de cierre, referencias cruzadas en dos idiomas, mensajes de commit y cuerpos de PR — y sólo los tres primeros son comprobables mecánicamente. `08-validate-tracking` no puede ayudar por construcción: valida dentro de un único árbol de trabajo, y las ramas quedan fuera de su mundo. Tampoco es un desliz aislado — en el merge `develop` → `main` del 2026-07-30 el mismo patrón de duplicación convergente aparece tres veces: GT-633 arreglado dos veces, el parser del guard de evidencias arreglado dos veces, este id asignado dos veces. | | | `Governance` | Cross | P2 | S | `PENDIENTE` |
| [`GT-635`](./gap-reference-catalog.es.md#gt-635) | **El ratchet de referencias muertas está por encima del presupuesto en main desde el 2026-07-28, así que el job de gobernanza está en rojo permanente.** `41-validate-evidence-commands --strict --max-dead 305` reporta **309 referencias muertas en un checkout limpio**, así que `Governance guards (GT-578)` sale 1 en cada corrida de `ci-cd.yml` — observado en las corridas `30482497995`, `30470648146` y `30466280865`, todas en `main` y sin nada por mergear. El presupuesto se fijó en `4a1b92d6` "donde se midió"; desde entonces diez commits han editado `gap-closure-evidence.json`, cada uno añadiendo `validationCommands`, y la cuenta se fue por encima. El propósito entero del ratchet es que las referencias muertas no CREZCAN, y está reportando exactamente eso mientras se lo ignora, porque un job en rojo permanente se lee como ruido de fondo — el mismo modo de fallo que [`GT-622`](./gap-reference-catalog.es.md#gt-622) registra para la configuración huérfana de CodeQL. El próximo cambio que añada de verdad una referencia muerta será indistinguible de las cuatro que ya están. **Lo que no hay que hacer:** subir el presupuesto a 309, que convierte un ratchet incumplido en uno ratificado. | | | `Governance` | Cross | P2 | S | `COMPLETADO` |
| [`GT-634`](./gap-reference-catalog.es.md#gt-634) | **El CLI y el MCP publicados resuelven una build del SDK anterior a la ola de seguridad, porque un rango caret bajo 1.x la fija.** `@beyondnet/evolith-cli@1.2.1` y `@beyondnet/evolith-mcp@1.2.1` declaran ambos `@beyondnet/evolith-sdk: ^1.1.0`, y eso resuelve **exactamente `1.1.0`** — el SDK publica `1.0.0`, `1.1.0` y `2.0.0` y nada en medio, y un caret no cruza un mayor. Las fechas son el hallazgo: `sdk@1.1.0` se publicó el 2026-07-18, `sdk@2.0.0` el 2026-07-27 como parte de la release que cerró [`GT-570`](./gap-reference-catalog.es.md#gt-570), y ambos consumidores el 2026-07-28 — **después** de que 2.0.0 existiera, y seguían en la línea 1.x. Así que la exposición que GT-570 declaró cerrada para "quien instale `latest`" no está cerrada para esta dependencia. Dicho con precisión, porque la afirmación fuerte no está verificada aquí: lo medido son las fechas y la resolución, no el contenido — esta fila no afirma que `sdk@1.1.0` cargue una vulnerabilidad concreta. Encontrado ejecutando el criterio de deprecación de [`GT-624`](./gap-reference-catalog.es.md#gt-624), que es lo que dejó el rango a la vista: deprecar `sdk@1.1.0` avisaría en cada instalación limpia de la línea actual sin ningún sucesor 1.x que ofrecer. **CERRADO el 2026-07-30 — 1.2.2 está publicada, y el marco de seguridad de esta fila era ERRÓNEO.** Una instalación limpia de `@beyondnet/evolith-cli@latest` resuelve ya `@beyondnet/evolith-sdk@2.0.0` con el binario arrancando. Pero verificar el criterio 2 refutó la premisa: **ninguno de los siete commits de la ola toca `src/packages/sdk-client` — cero ficheros** — y el propio commit de release de la ola nombra los tres paquetes afectados (mcp, cli, agent-runtime). El SDK se republicó con ellos, no se arregló. Lo real es un MAYOR rancio fijado por un caret bajo 1.x más un lockfile que anidaba el tarball del registry tapando el enlace del workspace — la clase de `GT-625`, no una exposición de seguridad. La cautela escrita al abrir la fila es lo que abarató la corrección. | | | `Infra` | Cross | P1 | S | `COMPLETADO` |
Expand Down Expand Up @@ -651,7 +652,7 @@ Este tablero es la única fuente de verdad para deuda técnica, gaps, oportunida
| [`GT-246`](./gap-reference-catalog.es.md#gt-246) | Implementar experimentos Chaos Mesh/Litmus | | | `QA` | Cross | P3 | L | `COMPLETADO` |


**Progreso:** 596 / 636 completados · 14 en progreso · 22 pendientes · 4 diferidos
**Progreso:** 596 / 637 completados · 14 en progreso · 23 pendientes · 4 diferidos

**Oleada 2026-06-23 (auditoría profunda de Winston III):** Añadidos 14 gaps nuevos `GT-212`…`GT-225` del Winston Audit Playbook que cubren: higiene de estado ADR (GT-212), metadata + presupuestos operativos + corpus de guías por topología (GT-213, GT-217, GT-219), observabilidad + OpenAPI en controladores REST (GT-214, GT-215), paridad de input-schemas OPA + densidad de tests por topología (GT-216, GT-222), plantillas de rollback + on-call de Fase 05 (GT-218), cobertura de ramas CLI + paridad de envelope --format + limpieza de skip-list (GT-220, GT-224, GT-225), audit logging HTTP de MCP (GT-221), y tests e2e de paridad cross-surface (GT-223).

Expand Down
Loading
Loading