From e6440463f66e49e30d6faf798fc5318670b28904 Mon Sep 17 00:00:00 2001 From: aarroyo Date: Sat, 1 Aug 2026 02:51:31 -0500 Subject: [PATCH] chore(gaps): record reliability k6 evidence --- reference/core/control-center/gaps/gap-reference-catalog.es.md | 3 ++- reference/core/control-center/gaps/gap-reference-catalog.md | 3 ++- reference/core/control-center/gaps/gap-tracking.es.md | 2 +- reference/core/control-center/gaps/gap-tracking.md | 2 +- 4 files changed, 6 insertions(+), 4 deletions(-) diff --git a/reference/core/control-center/gaps/gap-reference-catalog.es.md b/reference/core/control-center/gaps/gap-reference-catalog.es.md index 7c65e8aa..67eca10c 100644 --- a/reference/core/control-center/gaps/gap-reference-catalog.es.md +++ b/reference/core/control-center/gaps/gap-reference-catalog.es.md @@ -1901,11 +1901,12 @@ Detectado por el **spike Fase-0b de ADR-0109** al validar el workspace de monore - **Acceptance criteria:** - [x] Los tests de integración del circuit breaker ejercitan las transiciones abierto, semiabierto y cerrado contra una dependencia que falla, y fallan sin el breaker. - - [ ] Un perfil de carga K6 corre en CI y publica rendimiento, latencia p95 y tasa de error contra umbrales declarados. + - [x] Un perfil de carga K6 corre en CI y publica rendimiento, latencia p95 y tasa de error contra umbrales declarados. - [ ] Un simulacro de caos mata una dependencia a mitad de ejecución y el comportamiento registrado coincide con lo que declara ADR-0011. - [ ] RTO y RPO se MIDEN en una restauración DR real y se escriben en ADR-0013, sustituyendo la afirmación no cuantificada actual. - **Avance (2026-08-01):** El criterio de circuit breaker queda satisfecho por la suite de integración de agent-runtime, no por un test unitario aislado de la máquina de estados. `src/packages/agent-runtime/src/adapters/resilience/circuit-breaker.integration.spec.ts` levanta un sustituto real de Core con `node:http`, lo ejecuta mediante `HttpCoreEvaluationAdapter`, y afirma cerrado -> abierto, abierto -> semiabierto -> cerrado, semiabierto -> abierto, y timeout de una dependencia colgada. Cada camino protegido tiene un control sin breaker que prueba que la dependencia todavía recibe llamadas o sigue pendiente sin esa protección. Verificado localmente con `npm --prefix src/packages/agent-runtime test -- --runTestsByPath src/adapters/resilience/circuit-breaker.integration.spec.ts` (5/5 tests). +- **Avance (2026-08-01):** El criterio de K6 en CI queda satisfecho por el workflow `Reliability` en `main`, corrida `30687194238` (`83fbb042`). El job `k6 load profile (thresholds + published metrics)` pasó y subió `k6-reliability-30687194238`; el resumen de average-load registró 1.131 requests HTTP a **12,528 req/s**, `evaluate_latency` p95 **162,20 ms**, p99 **243,78 ms**, `evaluate_errors` **0%**, `throttled_429` **0%**, y todos los umbrales declarados en verde. La misma corrida también produjo un job verde de chaos/MTTR, pero esa evidencia todavía no cierra el criterio de matar una dependencia según ADR-0011: el target registrado fue `core-api`, mientras el criterio pide una dependencia a mitad de ejecución. DR RTO/RPO también queda abierto porque la corrida es un drill de restart de contenedores en un solo host, no una restauración DR real. #### GT-444 diff --git a/reference/core/control-center/gaps/gap-reference-catalog.md b/reference/core/control-center/gaps/gap-reference-catalog.md index 8983eb23..3e1d2321 100644 --- a/reference/core/control-center/gaps/gap-reference-catalog.md +++ b/reference/core/control-center/gaps/gap-reference-catalog.md @@ -1911,11 +1911,12 @@ Discovered by the **ADR-0109 Phase-0b spike** while validating the prospective m - **Acceptance criteria:** - [x] Circuit-breaker integration tests exercise open, half-open and closed transitions against a failing dependency, and fail without the breaker. - - [ ] A K6 load profile runs in CI and publishes throughput, p95 latency and error rate against declared thresholds. + - [x] A K6 load profile runs in CI and publishes throughput, p95 latency and error rate against declared thresholds. - [ ] One chaos drill kills a dependency mid-run and the recorded behaviour matches what ADR-0011 declares. - [ ] RTO and RPO are MEASURED on a real DR restore and written into ADR-0013, replacing the current unquantified claim. - **Progress (2026-08-01):** The circuit-breaker criterion is satisfied by the agent-runtime integration suite rather than by a unit-only state-machine test. `src/packages/agent-runtime/src/adapters/resilience/circuit-breaker.integration.spec.ts` boots a real `node:http` Core stand-in, drives it through `HttpCoreEvaluationAdapter`, and asserts closed -> open, open -> half-open -> closed, half-open -> open, and a hanging dependency timeout. Each protected path has an unprotected control proving the dependency is still called or still pending without the breaker. Verified locally with `npm --prefix src/packages/agent-runtime test -- --runTestsByPath src/adapters/resilience/circuit-breaker.integration.spec.ts` (5/5 tests). +- **Progress (2026-08-01):** The K6 CI criterion is now satisfied by the `Reliability` workflow on `main`, run `30687194238` (`83fbb042`). Job `k6 load profile (thresholds + published metrics)` passed and uploaded `k6-reliability-30687194238`; the average-load summary recorded 1,131 HTTP requests at **12.528 req/s**, `evaluate_latency` p95 **162.20 ms**, p99 **243.78 ms**, `evaluate_errors` **0%**, `throttled_429` **0%**, and all declared thresholds green. The same run also produced a green chaos/MTTR job, but that evidence does not close the ADR-0011 dependency-kill criterion yet: the recorded drill target was `core-api`, while the criterion asks for a dependency failure mid-run. DR RTO/RPO also remain open because the run is a single-host container restart drill, not a real DR restore. #### GT-444 diff --git a/reference/core/control-center/gaps/gap-tracking.es.md b/reference/core/control-center/gaps/gap-tracking.es.md index 7c024ac1..53eaa68a 100644 --- a/reference/core/control-center/gaps/gap-tracking.es.md +++ b/reference/core/control-center/gaps/gap-tracking.es.md @@ -205,7 +205,7 @@ Este tablero es la única fuente de verdad para deuda técnica, gaps, oportunida | [`GT-440`](./gap-reference-catalog.es.md#gt-440) | Completar observabilidad: añadir `/metrics` (Prometheus) a `mcp-server` + `agent-runtime-api`; `OTEL_EXPORTER_OTLP_ENDPOINT` configurable; split liveness/readiness. **HECHO (b3c6557f): `/metrics` en los 3 servicios (core-api existente + mcp `evolith_mcp_*` + agent-runtime `evolith_agent_runtime_*`), `/health/live`+`/health/ready` en mcp+agent-runtime, OTEL endpoint por env. Verificado en el stack local (todos 200).** | `Observability` | Cross | P1 | M | `COMPLETADO` | | [`GT-441`](./gap-reference-catalog.es.md#gt-441) | El sistema puede pedir aprobación humana para una acción sensible, pero todavía no existe nada que reciba la petición **Qué significa:** Antes de hacer algo sensible el sistema debe detenerse y esperar a una persona. Se detiene bien, pero la petición no le llega a nadie, así que siempre termina rechazada **Ejemplo:** Toda acción marcada como que requiere aprobación vuelve rechazada con «no se pudo preguntar», porque el lugar elegido para responder aún no se ha construido. **Cierre (`a299ab89`):** el receptor ya existe. El Tracker embarcó el endpoint (CD-23, migración `AddRuntimeApprovals`, 2026-07-19) y el Core embarcó el `TrackerApprovalHttpClient` concreto tras el seam de GT-441 — POST `/runtime-approvals` con la clave CoreMachine (el tenant se deriva de QUÉ clave hizo match, nunca del body); un non-2xx lanza para que el adapter deniegue fail-closed como «unavailable» — wireado opt-in en `runtime.factory` (`AGENT_RUNTIME_APPROVAL_TRACKER_URL`/`_KEY`, mandatorio en production). Live-smoke contra el Tracker corriendo: submit → pending (persistido en Postgres) → el adapter deniega fail-closed → idempotente por `correlationId` → un rechazo humano vuelve como denegación `tracker-decision`. El camino approve→grant exige un aprobador UMS designado (CD-31; el dev-bypass deliberadamente no puede serlo), así que queda cubierto por unit + tests del lado Tracker. package 249/249 + app 81/81 verdes. | `Agent Runtime` | Cross | P1 | M | `COMPLETADO` | | [`GT-442`](./gap-reference-catalog.es.md#gt-442) | Estrategia de secrets + conectividad a DB de producción: documentar/cablear un secret store (Coolify vault / K8s secrets) para `EVOLITH_API_KEY` etc., y aclarar `DATABASE_URL`/config de conexión (ausente en el deploy config hoy). **Cierre (accepted-scope) — ambas mitades del enunciado estaban desalineadas con el código.** (1) *Secret store: sustancialmente ya entregado* — los tres charts toman credenciales de un Secret de K8s pre-creado **por nombre** vía `secretKeyRef`, gated por `auth.existingSecretName` (`core-api-auth`, `mcp-auth`, `agent-runtime-auth`; más `opa-bundle-credentials` / `opa-bundle-signing-key` en mcp). Ningún chart incrusta un literal. El gap real era que estaba sin documentar y disperso → ahora consolidado en `product/infra/README.md`(+`.es.md`) §*Secretos y Conectividad de Datos*, con el equivalente Coolify (variable de entorno cifrada). (2) *Conectividad a DB: **NO APLICA al Core*** — `core-api` y `agent-runtime-api` declaran **cero** dependencias de DB (sin driver/ORM/cadena de conexión, verificado contra ambos `package.json`). Es **ADR-0101 por diseño**: el Core es un motor de evaluación stateless (`EvaluationContext`→`EvaluationResult`; producto/tenant/iniciativa son contexto opaco, nunca persistidos). Así que `DATABASE_URL` no está "faltando" — no hay a qué conectarse, y añadirla *contradiría* ADR-0101. Las cadenas `postgresql` en `projects.controller.ts`/`core-domain.module.ts` son el **generador de scaffolding** eligiendo DB para el proyecto *generado*. La persistencia vive en el **Tracker** (su propio Postgres `tracker_governance`) → trabajo de conectividad de DB delegado al board de ese repo. **Pendiente (owner-gated, no código):** aprovisionar los valores reales de los secretos en el VPS/cluster — mismo bloqueo que [`GT-324`](./gap-reference-catalog.es.md#gt-324)/[`GT-437`](./gap-reference-catalog.es.md#gt-437). | `Infra` | Cross | P1 | S | `COMPLETADO` | -| [`GT-443`](./gap-reference-catalog.es.md#gt-443) | Nunca se midió en un despliegue real cómo se comporta el sistema ante fallos y bajo carga alta **2026-07-28: por fin tiene criterios de aceptación.** Esta fila llevaba EN-PROGRESO con CERO criterios de aceptación — su sección solo tenía prosa ("Closure: breaker integration tests + K6 load/chaos + DR deploy with measured RTO/RPO"), así que nadie podía cerrarla, porque nada definía qué era estar hecho. `08-validate-tracking` no lo detectaba: verifica que una fila DONE tenga sus criterios marcados, y no dice nada sobre que una fila EN-PROGRESO tenga criterios siquiera. La prosa son ahora cuatro criterios comprobables; el hueco del guard queda registrado como `GT-629`. **Avance 2026-08-01:** el criterio de integración del circuit breaker ya queda marcado: el test de agent-runtime levanta una dependencia HTTP real, cubre transiciones cerrado/abierto/semiabierto más timeout, y lleva controles sin protección. K6, chaos y DR siguen abiertos. **Qué significa:** Decimos que el sistema sigue funcionando cuando algo se rompe o cuando llega mucho tráfico. Eso solo se comprobó en pruebas aisladas, nunca sobre algo realmente en marcha **Ejemplo:** Nadie sabe cuánto tardaría el servicio en volver tras una caída total, porque ese tiempo de recuperación nunca se ha cronometrado | `Reliability` | Cross | P2 | L | `EN-PROGRESO` | +| [`GT-443`](./gap-reference-catalog.es.md#gt-443) | Nunca se midió en un despliegue real cómo se comporta el sistema ante fallos y bajo carga alta **2026-07-28: por fin tiene criterios de aceptación.** Esta fila llevaba EN-PROGRESO con CERO criterios de aceptación — su sección solo tenía prosa ("Closure: breaker integration tests + K6 load/chaos + DR deploy with measured RTO/RPO"), así que nadie podía cerrarla, porque nada definía qué era estar hecho. `08-validate-tracking` no lo detectaba: verifica que una fila DONE tenga sus criterios marcados, y no dice nada sobre que una fila EN-PROGRESO tenga criterios siquiera. La prosa son ahora cuatro criterios comprobables; el hueco del guard queda registrado como `GT-629`. **Avance 2026-08-01:** el criterio de integración del circuit breaker ya queda marcado: el test de agent-runtime levanta una dependencia HTTP real, cubre transiciones cerrado/abierto/semiabierto más timeout, y lleva controles sin protección. El criterio de K6 en CI también queda marcado desde la corrida Reliability `30687194238` en `main`: 1.131 requests HTTP a 12,528 req/s, evaluate p95 162,20 ms, p99 243,78 ms, 0% errores de evaluación y todos los umbrales en verde. El criterio de chaos contra una dependencia y el RTO/RPO de DR real siguen abiertos. **Qué significa:** Decimos que el sistema sigue funcionando cuando algo se rompe o cuando llega mucho tráfico. Eso solo se comprobó en pruebas aisladas, nunca sobre algo realmente en marcha **Ejemplo:** Nadie sabe cuánto tardaría el servicio en volver tras una caída total, porque ese tiempo de recuperación nunca se ha cronometrado | `Reliability` | Cross | P2 | L | `EN-PROGRESO` | | [`GT-444`](./gap-reference-catalog.es.md#gt-444) | Ningún tercero externo ha intentado nunca entrar por la fuerza al sistema en marcha **Qué significa:** Hay herramientas automáticas que buscan debilidades ya catalogadas. Nadie ha sido contratado para atacar el sistema en vivo como lo haría un intruso real, así que los agujeros desconocidos siguen siendo desconocidos **Ejemplo:** Toda la postura de seguridad se apoya en dos escáneres automáticos; no existe ningún informe de un atacante humano | `Security` | Cross | P2 | S | `PENDIENTE` | | [`GT-552`](./gap-reference-catalog.es.md#gt-552) | **`release-please` apunta a archivos de configuración que ya no existen, así que nunca puede cortar una versión.** `sdk-cli-release.yml` pasa `config-file: release-please-config.json` y `manifest-file: .release-please-manifest.json`, ambos BORRADOS en `aed33ba9` ("versioning managed manually"), ausentes tanto en `main` como en `develop` y no gitignorados. En consecuencia `release_created` nunca puede ser `true`: los jobs de publicación npm, empaquetado de binarios, smoke-test y subida de assets son inalcanzables, y el ÚNICO workflow del repositorio que crea un Issue automáticamente (`failure-notification`) es código muerto condicionado a esa misma salida. Fix: restaurar los dos archivos de config o migrar el workflow a la realidad de versionado manual que declara. **Cierre (`38db17bf`):** el workflow ya no referencia `release-please-config.json` / `.release-please-manifest.json` (ambos borrados en `aed33ba9`), y el job huérfano `release-please` fue reemplazado por un job `release-gate`, de modo que el workflow ya no declara que puede cortar una versión automáticamente. **Corrección al enunciado original:** el job `failure-notification` NO es código muerto inalcanzable -- SE EJECUTÓ Y TUVO ÉXITO en la corrida 29641024724. El pipeline de release sigue fallando por motivos no relacionados, ahora rastreados por [`GT-561`](./gap-reference-catalog.es.md#gt-561), [`GT-562`](./gap-reference-catalog.es.md#gt-562) y [`GT-563`](./gap-reference-catalog.es.md#gt-563); este gap trataba del CABLEADO roto, que está arreglado. | `Infra` | Cross | P1 | S | `COMPLETADO` | | [`GT-553`](./gap-reference-catalog.es.md#gt-553) | **`09-reconcile-maturity.mjs` arrastra constantes de ruta muertas y cuenta mal los rulesets.** CUATRO constantes derivan del borrado `reference/core/sdlc/standards/vision/` — `VISION_DIR` y las tres construidas desde ella (`BOARD`, `REGISTRY`, `RUNTIME_EVIDENCE`); estas tres se referencian solo en su propia declaración, así que el clúster es inerte (el guard funciona por lecturas hardcodeadas correctas a `control-center/`). Aparte, `rulesetCount` escanea `rulesets/` en vez de `src/rulesets/`, y por eso el snapshot commiteado de `maturity-reconciliation.json` reporta `"rulesetCount": 0`. Fix: borrar las constantes muertas y reapuntar el escaneo de rulesets a `src/rulesets/`. **Cierre (`35ea46e1`):** el criterio 1 quedó satisfecho por [`GT-556`](./gap-reference-catalog.es.md#gt-556) -- todas las constantes resuelven ahora vía `resolveKey`, y la única mención restante de `vision/` es un comentario explicativo; el criterio 2 está satisfecho y el snapshot regenerado, con `rulesetCount` reportando **145**, coincidiendo con `find src/rulesets -name "*.rules.json" \| wc -l`. **Corrección:** el snapshot commiteado sí llevaba el campo, como `0` -- no estaba ausente, y ese cero era el síntoma. | `Governance` | Cross | P2 | S | `COMPLETADO` | diff --git a/reference/core/control-center/gaps/gap-tracking.md b/reference/core/control-center/gaps/gap-tracking.md index 81c50abf..fd3aca3b 100644 --- a/reference/core/control-center/gaps/gap-tracking.md +++ b/reference/core/control-center/gaps/gap-tracking.md @@ -205,7 +205,7 @@ This board is the single source of truth for technical debt, gaps, opportunities | [`GT-440`](./gap-reference-catalog.md#gt-440) | Observability completeness: add `/metrics` (Prometheus) to `mcp-server` + `agent-runtime-api`; `OTEL_EXPORTER_OTLP_ENDPOINT` configurable; liveness/readiness split. **Closure (b3c6557f): `/metrics` on all 3 services (core-api existing + mcp `evolith_mcp_*` + agent-runtime `evolith_agent_runtime_*`), `/health/live`+`/health/ready` on mcp+agent-runtime, OTEL endpoint via env. Verified on the local stack (all 200).** | `Observability` | Cross | P1 | M | `DONE` | | [`GT-441`](./gap-reference-catalog.md#gt-441) | The system can ask a human to approve a sensitive action, but nothing exists yet to receive the request **What it means:** Before doing anything sensitive the system is supposed to stop and wait for a person. It stops correctly, but the request never reaches anybody, so it always ends in a refusal **Example:** Every action marked as needing approval comes back refused with "could not ask", because the place chosen to answer has not been built yet. **Closure (`a299ab89`):** the receiver now exists. The Tracker shipped the endpoint (CD-23, migration `AddRuntimeApprovals`, 2026-07-19) and the Core shipped the concrete `TrackerApprovalHttpClient` behind the GT-441 seam — POST `/runtime-approvals` with the CoreMachine key (the tenant is derived from WHICH key matched, never the body); a non-2xx throws so the adapter denies fail-closed as "unavailable" — wired opt-in in `runtime.factory` (`AGENT_RUNTIME_APPROVAL_TRACKER_URL`/`_KEY`, mandatory under production). Live-smoked against the running Tracker: submit → pending (persisted in Postgres) → adapter denies fail-closed → idempotent by `correlationId` → a human reject flows back as a `tracker-decision` denial. The approve→grant path needs a designated UMS approver (CD-31; dev-bypass deliberately cannot be one) so it stays covered by unit + Tracker-side tests. package 249/249 + app 81/81 green. | `Agent Runtime` | Cross | P1 | M | `DONE` | | [`GT-442`](./gap-reference-catalog.md#gt-442) | Production secrets + DB connectivity strategy: document/wire a secret store (Coolify vault / K8s secrets) for `EVOLITH_API_KEY` etc., and clarify `DATABASE_URL`/connection config (absent from the deploy config today). **Closure (accepted-scope) — both halves of the framing were misaligned with the codebase.** (1) *Secret store: substantially already delivered* — all three charts take credentials from a pre-created K8s Secret **by name** via `secretKeyRef`, gated on `auth.existingSecretName` (`core-api-auth`, `mcp-auth`, `agent-runtime-auth`; plus `opa-bundle-credentials` / `opa-bundle-signing-key` on mcp). No chart embeds a literal. The real gap was that this was undocumented and scattered → now consolidated in `product/infra/README.md`(+`.es.md`) §*Secrets and Data Connectivity*, with the Coolify (encrypted env var) equivalent. (2) *DB connectivity: **NOT APPLICABLE to the Core*** — `core-api` and `agent-runtime-api` declare **zero** DB dependencies (no driver/ORM/connection string, verified against both `package.json`). That is **ADR-0101 by design**: the Core is a stateless evaluation engine (`EvaluationContext`→`EvaluationResult`; product/tenant/initiative are opaque context, never persisted). So `DATABASE_URL` is not "missing" — there is nothing to connect to, and adding it would *contradict* ADR-0101. The `postgresql` strings in `projects.controller.ts`/`core-domain.module.ts` are the **scaffolding generator** choosing a DB for the *generated* project. Persistence lives in the **Tracker** (own Postgres `tracker_governance`) → DB-connectivity work delegated to that repo's board. **Remaining (owner-gated, not code):** provisioning the real secret values on the VPS/cluster — same blocker as [`GT-324`](./gap-reference-catalog.md#gt-324)/[`GT-437`](./gap-reference-catalog.md#gt-437). | `Infra` | Cross | P1 | S | `DONE` | -| [`GT-443`](./gap-reference-catalog.md#gt-443) | How the system behaves under failure and heavy load has never been measured on a running deployment **2026-07-28: given acceptance criteria at last.** This row sat IN-PROGRESS with ZERO acceptance criteria — its section carried only prose ("Closure: breaker integration tests + K6 load/chaos + DR deploy with measured RTO/RPO"), so it could not be closed by anybody, because nothing defined done. `08-validate-tracking` did not catch it: it verifies that a DONE row has its criteria ticked, and says nothing about an IN-PROGRESS row having criteria at all. The prose is now four checkable criteria; the guard gap is registered as `GT-629`. **2026-08-01 progress:** the circuit-breaker integration criterion is now checked off: the agent-runtime test boots a real HTTP dependency, covers closed/open/half-open transitions plus timeout, and carries unprotected controls. K6, chaos and DR measurements remain open. **What it means:** We say the system keeps working when parts of it break or when traffic spikes. That claim has only been checked in isolated tests, never against something actually running **Example:** Nobody can say how long the service would take to come back after a total outage, because that recovery time has never been timed | `Reliability` | Cross | P2 | L | `IN-PROGRESS` | +| [`GT-443`](./gap-reference-catalog.md#gt-443) | How the system behaves under failure and heavy load has never been measured on a running deployment **2026-07-28: given acceptance criteria at last.** This row sat IN-PROGRESS with ZERO acceptance criteria — its section carried only prose ("Closure: breaker integration tests + K6 load/chaos + DR deploy with measured RTO/RPO"), so it could not be closed by anybody, because nothing defined done. `08-validate-tracking` did not catch it: it verifies that a DONE row has its criteria ticked, and says nothing about an IN-PROGRESS row having criteria at all. The prose is now four checkable criteria; the guard gap is registered as `GT-629`. **2026-08-01 progress:** the circuit-breaker integration criterion is now checked off: the agent-runtime test boots a real HTTP dependency, covers closed/open/half-open transitions plus timeout, and carries unprotected controls. The K6 CI criterion is also checked off from Reliability run `30687194238` on `main`: 1,131 HTTP requests at 12.528 req/s, evaluate p95 162.20 ms, p99 243.78 ms, 0% evaluate errors and all thresholds green. The dependency-kill chaos criterion and real DR RTO/RPO remain open. **What it means:** We say the system keeps working when parts of it break or when traffic spikes. That claim has only been checked in isolated tests, never against something actually running **Example:** Nobody can say how long the service would take to come back after a total outage, because that recovery time has never been timed | `Reliability` | Cross | P2 | L | `IN-PROGRESS` | | [`GT-444`](./gap-reference-catalog.md#gt-444) | No outside party has ever attempted to break into the running system **What it means:** Automated tools scan the code for weaknesses that are already catalogued. Nobody has been hired to actively attack the live system the way a real intruder would, so unknown holes stay unknown **Example:** The entire security position rests on two automated scanners; there is no report from a human attacker | `Security` | Cross | P2 | S | `PENDING` | | [`GT-552`](./gap-reference-catalog.md#gt-552) | **`release-please` is wired to configuration files that no longer exist, so no version can ever be cut.** `sdk-cli-release.yml` passes `config-file: release-please-config.json` and `manifest-file: .release-please-manifest.json`, both DELETED in `aed33ba9` ("versioning managed manually"), present in neither `main` nor `develop` and not gitignored. Consequently `release_created` can never be `true`: the npm publish, binary packaging, smoke-test and asset-upload jobs are unreachable, and the repository's ONLY workflow that auto-creates a GitHub Issue (`failure-notification`) is dead code gated on that same output. Fix: restore the two config files or migrate the workflow to the manual-versioning reality it claims. **Closure (`38db17bf`):** the workflow no longer references `release-please-config.json` / `.release-please-manifest.json` (both deleted in `aed33ba9`), and the orphaned `release-please` job was replaced by a `release-gate` job, so the workflow no longer claims it can auto-cut a version. **Correction to the original write-up:** the `failure-notification` job is NOT unreachable dead code -- it RAN AND SUCCEEDED in run 29641024724. The release pipeline still fails for unrelated reasons, now tracked by [`GT-561`](./gap-reference-catalog.md#gt-561), [`GT-562`](./gap-reference-catalog.md#gt-562) and [`GT-563`](./gap-reference-catalog.md#gt-563); this gap was about the broken WIRING, which is fixed. | `Infra` | Cross | P1 | S | `DONE` | | [`GT-553`](./gap-reference-catalog.md#gt-553) | **`09-reconcile-maturity.mjs` carries dead path constants and miscounts rulesets.** FOUR constants derive from the deleted `reference/core/sdlc/standards/vision/` — `VISION_DIR` and the three built from it (`BOARD`, `REGISTRY`, `RUNTIME_EVIDENCE`); the latter three are each referenced only by their own declaration, so the cluster is inert (the guard works via correct hardcoded `control-center/` reads). Separately `rulesetCount` scans `rulesets/` instead of `src/rulesets/`, which is why the committed `maturity-reconciliation.json` snapshot reports `"rulesetCount": 0`. Fix: delete the dead constants and repoint the ruleset scan to `src/rulesets/`. **Closure (`35ea46e1`):** criterion 1 was satisfied by [`GT-556`](./gap-reference-catalog.md#gt-556) -- all constants now resolve through `resolveKey`, and the only remaining mention of `vision/` is an explanatory comment; criterion 2 is satisfied and the snapshot regenerated, `rulesetCount` now reporting **145**, matching `find src/rulesets -name "*.rules.json" \| wc -l`. **Correction:** the committed snapshot did carry the field, as `0` -- it was not absent, and that zero was the symptom. | `Governance` | Cross | P2 | S | `DONE` |