<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" xml:lang="es"><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="https://luisgonzalezbernal.com/feed.xml" rel="self" type="application/atom+xml" /><link href="https://luisgonzalezbernal.com/" rel="alternate" type="text/html" hreflang="es" /><updated>2026-10-18T11:55:03+00:00</updated><id>https://luisgonzalezbernal.com/feed.xml</id><title type="html">Luis González Bernal</title><subtitle>SRE, AI Engineer y profesor. Mantengo sistemas en producción, construyo productos con IA y enseño Python y DevOps.</subtitle><entry><title type="html">La checklist que salvó un despliegue de viernes</title><link href="https://luisgonzalezbernal.com/blog/demo-checklist-despliegue-viernes/" rel="alternate" type="text/html" title="La checklist que salvó un despliegue de viernes" /><published>2026-10-18T10:30:00+00:00</published><updated>2026-10-18T10:30:00+00:00</updated><id>https://luisgonzalezbernal.com/blog/demo-checklist-despliegue-viernes</id><content type="html" xml:base="https://luisgonzalezbernal.com/blog/demo-checklist-despliegue-viernes/"><![CDATA[<div class="nota">
  <p><b>Entrada de demostración.</b> Está publicada para ver cómo queda el blog con contenido real:
  tabla, código, listas y cita. Se borra cuando ya no haga falta. Lleva <code>noindex</code> y no
  aparece en el <code>sitemap</code>.</p>
</div>

<p>Los despliegues de viernes tienen mala fama por una razón que casi nunca se dice en voz alta: no
falla el código, falla la memoria de quien despliega. A las seis de la tarde, con prisa por cerrar,
nadie recuerda si el <code class="language-plaintext highlighter-rouge">feature flag</code> está apagado, si la migración es reversible o si el backup de
las cuatro es el bueno.</p>

<p>Así que dejamos de confiar en que alguien se acordara y escribimos la lista. No es una lista de
deseos: cada punto es una comprobación que devuelve <code class="language-plaintext highlighter-rouge">sí</code> o <code class="language-plaintext highlighter-rouge">no</code>, y un <code class="language-plaintext highlighter-rouge">no</code> detiene el despliegue sin
discusión.</p>

<h2 id="la-lista-en-orden">La lista, en orden</h2>

<ol>
  <li><strong>El cambio está detrás de un flag</strong> y el flag está apagado en producción.</li>
  <li><strong>La migración tiene <code class="language-plaintext highlighter-rouge">down</code></strong> y se ha probado en el entorno de staging de esta semana, no del mes
pasado.</li>
  <li><strong>El SLO tiene presupuesto</strong> para el error que vamos a introducir. Si el presupuesto del mes ya
está gastado, no se despliega: se arregla primero la estabilidad.</li>
  <li><strong>El rollback está ensayado</strong> al menos una vez, y sabemos cuánto tarda (no «debería ser rápido»).</li>
  <li><strong>Alguien mira el dashboard</strong> durante los veinte minutos siguientes, con nombre y apellidos.</li>
</ol>

<h2 id="por-qué-el-punto-3-es-el-que-más-discusiones-ahorra">Por qué el punto 3 es el que más discusiones ahorra</h2>

<p>El presupuesto de error convierte una discusión de opiniones en una resta. Antes de la lista,
decidir si un despliegue «urgía» dependía de quién hablaba más alto en el canal. Ahora es un número:</p>

<table>
  <thead>
    <tr>
      <th>Situación</th>
      <th>Presupuesto</th>
      <th>Decisión</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Mes tranquilo, sin incidentes</td>
      <td>100 % disponible</td>
      <td>Se despliega</td>
    </tr>
    <tr>
      <td>Un incidente Sev-2 ya consumido</td>
      <td>~35 %</td>
      <td>Se despliega con vigilancia</td>
    </tr>
    <tr>
      <td>Dos incidentes y un Sev-1</td>
      <td>0 %</td>
      <td>Se congela todo hasta cerrar la causa</td>
    </tr>
  </tbody>
</table>

<p>Nadie discute una tabla. Y cuando alguien quiere saltársela, la conversación ya no es «creo que
podemos», es «¿qué vas a quitar de la tabla y por qué?», que es una pregunta mucho más incómoda de
responder.</p>

<h2 id="el-chequeo-automatizado">El chequeo, automatizado</h2>

<p>La lista vive en el repositorio y corre sola antes de cada release. Lo importante no es el script:
es que si falla, el despliegue no sigue.</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">listo_para_desplegar</span><span class="p">(</span><span class="n">slo</span><span class="p">,</span> <span class="n">flags</span><span class="p">,</span> <span class="n">migracion</span><span class="p">):</span>
    <span class="s">"""Devuelve (bool, motivos). Un solo 'no' bloquea el release."""</span>
    <span class="n">motivos</span> <span class="o">=</span> <span class="p">[]</span>

    <span class="k">if</span> <span class="n">slo</span><span class="p">[</span><span class="s">"presupuesto_restante"</span><span class="p">]</span> <span class="o">&lt;=</span> <span class="mi">0</span><span class="p">:</span>
        <span class="n">motivos</span><span class="p">.</span><span class="n">append</span><span class="p">(</span><span class="s">"sin presupuesto de error: se congela el release"</span><span class="p">)</span>

    <span class="k">if</span> <span class="ow">not</span> <span class="n">flags</span><span class="p">[</span><span class="s">"apagados_en_produccion"</span><span class="p">]:</span>
        <span class="n">motivos</span><span class="p">.</span><span class="n">append</span><span class="p">(</span><span class="s">"hay flags activos: el cambio no es reversible al instante"</span><span class="p">)</span>

    <span class="k">if</span> <span class="ow">not</span> <span class="n">migracion</span><span class="p">[</span><span class="s">"tiene_down"</span><span class="p">]</span> <span class="ow">or</span> <span class="ow">not</span> <span class="n">migracion</span><span class="p">[</span><span class="s">"probada_esta_semana"</span><span class="p">]:</span>
        <span class="n">motivos</span><span class="p">.</span><span class="n">append</span><span class="p">(</span><span class="s">"migración sin 'down' probado esta semana"</span><span class="p">)</span>

    <span class="k">return</span> <span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">motivos</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">,</span> <span class="n">motivos</span><span class="p">)</span>
</code></pre></div></div>

<p>Cuarenta líneas y un <code class="language-plaintext highlighter-rouge">if</code>. No hace falta una plataforma: hace falta que el <code class="language-plaintext highlighter-rouge">if</code> esté en el camino
crítico y no en un wiki que nadie abre.</p>

<blockquote>
  <p>Una checklist no existe para que la gente se acuerde de las cosas. Existe para que no pueda
fingir que se acordó.</p>
</blockquote>

<h2 id="lo-que-la-lista-no-arregla">Lo que la lista no arregla</h2>

<p>No arregla el código malo, ni la falta de tests, ni que el equipo vaya con prisa porque el backlog
está mal priorizado. Lo que hace es que el error se cometa con los ojos abiertos y quede en el
registro: quién desplegó, a qué hora y con qué comprobaciones en verde. Cuando algo se tuerce, la
revisión empieza por datos y no por recuerdos.</p>

<hr />

<p><em>Este texto es una demostración del formato del blog: tabla, código con resaltado, cita y lista
numerada. El contenido es inventado para la prueba.</em></p>]]></content><author><name></name></author><summary type="html"><![CDATA[Un despliegue de viernes por la tarde dejó de dar miedo cuando dejamos de fiarnos de la memoria y empezamos a fiarnos de una lista. Esta es la que corre antes de cada release.]]></summary></entry><entry><title type="html">Cómo etiqueto lo que escribo cuando hay un modelo detrás</title><link href="https://luisgonzalezbernal.com/blog/como-etiqueto-lo-que-escribo/" rel="alternate" type="text/html" title="Cómo etiqueto lo que escribo cuando hay un modelo detrás" /><published>2026-10-18T08:00:00+00:00</published><updated>2026-10-18T08:00:00+00:00</updated><id>https://luisgonzalezbernal.com/blog/como-etiqueto-lo-que-escribo</id><content type="html" xml:base="https://luisgonzalezbernal.com/blog/como-etiqueto-lo-que-escribo/"><![CDATA[<p>Escribo con modelos todos los días. Me ahorran horas en borradores, en código que no me apetece
teclear y en leer documentación que no tiene piedad. Lo que no quiero es que el lector tenga que
adivinar cuánto de lo que lee lo escribió una máquina.</p>

<p>La mayoría de blogs que usan IA esconder ese detalle, o lo esconden tan bien que da igual. La
alternativa no es confesar culpas: es dar información. Un artículo que un modelo redactó entero y
nadie verificó no vale lo mismo que uno escrito desde la experiencia y revisado línea a línea. Si
etiqueto, el lector decide. Si no etiqueto, decido yo por él, y eso es peor.</p>

<h2 id="la-etiqueta-como-la-de-un-producto">La etiqueta, como la de un producto</h2>

<p>Un envase no te dice si el contenido es bueno, pero te dice qué lleva. Con un texto pasa lo mismo:
saber que un modelo propuso la estructura ya te dice algo útil sobre lo que tienes delante, sin
quitarle mérito al resultado.</p>

<p>Así que cada entrada lleva dos cosas. Arriba, junto a la fecha, un <strong>nivel</strong> de un vistazo. Al pie,
una <strong>ficha de autoría</strong> que desglosa el proceso fase por fase: idea, estructura, código, redacción,
verificación.</p>

<h2 id="la-escala">La escala</h2>

<ul>
  <li><strong>Nivel 1 — humano.</strong> La IA no participó ni en la ideación ni en la redacción.</li>
  <li><strong>Nivel 2 — co-creado.</strong> La IA ayudó con estructura, borradores o reescritura; el control
editorial y la validación son míos, y el texto final está reescrito a mano.</li>
  <li><strong>Nivel 3 — asistencia puntual.</strong> El artículo es mío de principio a fin; la IA corrigió gramática,
buscó sinónimos o tradujo un fragmento.</li>
  <li><strong>Nivel 4 — supervisado.</strong> Redactado por un modelo y validado por mí antes de publicar.</li>
</ul>

<p>El Nivel 2 y el Nivel 3 se confunden a menudo, y no son lo mismo. La diferencia no es cuánta IA se
usó, sino <strong>de quién es el texto</strong>. En el Nivel 3 la IA es una herramienta de corrección. En el
Nivel 2 la estructura del artículo nació de una conversación con el modelo, aunque después reescriba
todo lo que se publica.</p>

<h2 id="cómo-está-montado-sin-nada-mágico">Cómo está montado, sin nada mágico</h2>

<p>El blog es Markdown servido por Jekyll en GitHub Pages. No hay base de datos, ni panel, ni servicio
de terceros: escribir es crear un fichero y hacer <code class="language-plaintext highlighter-rouge">git push</code>. La etiqueta son cuatro campos en el
frontmatter, y la tabla se genera desde ellos.</p>

<div class="language-yaml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nn">---</span>
<span class="na">layout</span><span class="pi">:</span> <span class="s">post</span>
<span class="na">title</span><span class="pi">:</span> <span class="s2">"</span><span class="s">Cómo</span><span class="nv"> </span><span class="s">etiqueto</span><span class="nv"> </span><span class="s">lo</span><span class="nv"> </span><span class="s">que</span><span class="nv"> </span><span class="s">escribo</span><span class="nv"> </span><span class="s">cuando</span><span class="nv"> </span><span class="s">hay</span><span class="nv"> </span><span class="s">un</span><span class="nv"> </span><span class="s">modelo</span><span class="nv"> </span><span class="s">detrás"</span>
<span class="na">date</span><span class="pi">:</span> <span class="s">2026-10-18 10:00:00 +0200</span>
<span class="na">permalink</span><span class="pi">:</span> <span class="s">/blog/como-etiqueto-lo-que-escribo/</span>
<span class="na">ia_nivel</span><span class="pi">:</span> <span class="m">2</span>
<span class="na">ia_humano_pct</span><span class="pi">:</span> <span class="m">85</span>
<span class="na">ia_fases</span><span class="pi">:</span>
  <span class="pi">-</span> <span class="na">fase</span><span class="pi">:</span> <span class="s2">"</span><span class="s">💡</span><span class="nv"> </span><span class="s">Idea</span><span class="nv"> </span><span class="s">y</span><span class="nv"> </span><span class="s">perspectiva"</span>
    <span class="na">quien</span><span class="pi">:</span> <span class="s">humano</span>
    <span class="na">detalle</span><span class="pi">:</span> <span class="s2">"</span><span class="s">Decisión</span><span class="nv"> </span><span class="s">personal,</span><span class="nv"> </span><span class="s">basada</span><span class="nv"> </span><span class="s">en</span><span class="nv"> </span><span class="s">cómo</span><span class="nv"> </span><span class="s">trabajo</span><span class="nv"> </span><span class="s">a</span><span class="nv"> </span><span class="s">diario."</span>
  <span class="pi">-</span> <span class="na">fase</span><span class="pi">:</span> <span class="s2">"</span><span class="s">✍️</span><span class="nv"> </span><span class="s">Redacción</span><span class="nv"> </span><span class="s">y</span><span class="nv"> </span><span class="s">tono"</span>
    <span class="na">quien</span><span class="pi">:</span> <span class="s">hibrido</span>
    <span class="na">detalle</span><span class="pi">:</span> <span class="s2">"</span><span class="s">Borrador</span><span class="nv"> </span><span class="s">inicial</span><span class="nv"> </span><span class="s">con</span><span class="nv"> </span><span class="s">IA;</span><span class="nv"> </span><span class="s">reescritura</span><span class="nv"> </span><span class="s">completa</span><span class="nv"> </span><span class="s">a</span><span class="nv"> </span><span class="s">mano."</span>
<span class="nn">---</span>
</code></pre></div></div>

<p>La plantilla recorre <code class="language-plaintext highlighter-rouge">ia_fases</code> y pinta la tabla; el nivel se convierte en una insignia de color con
su enlace a esta explicación. Como el dato vive en los metadatos y no en el cuerpo del texto, no
puede desincronizarse de la entrada: si alguien cambia la ficha, cambia el frontmatter, y el cambio
queda en el historial de git con fecha y autor.</p>

<h2 id="lo-que-esto-no-resuelve">Lo que esto no resuelve</h2>

<p>La etiqueta declara un proceso, no lo garantiza. Nadie audita que mi Nivel 1 sea realmente Nivel 1.
Es un compromiso público, y por eso funciona: si mañana publico aquí un texto generado entero y lo
etiqueto como Nivel 1, cualquiera puede señalarlo. La transparencia útil no es la que se demuestra
con un sello de calidad, sino la que se puede contradecir.</p>]]></content><author><name></name></author><summary type="html"><![CDATA[Un blog con IA detrás debería decirlo. Este es el sistema que uso: un nivel visible en cada entrada y una ficha que desglosa, fase por fase, qué hizo una persona y qué hizo una máquina.]]></summary></entry></feed>