<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/">
    <channel>
        <title>StrayMark Blog</title>
        <link>https://straymark.dev/es/blog</link>
        <description>The StrayMark chronicle.</description>
        <lastBuildDate>Sat, 23 May 2026 00:00:00 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <language>es</language>
        <copyright>Copyright © 2026 Strange Days Tech.</copyright>
        <item>
            <title><![CDATA[Lo que el binario no pudo esconder]]></title>
            <link>https://straymark.dev/es/blog/what-the-binary-couldnt-hide</link>
            <guid>https://straymark.dev/es/blog/what-the-binary-couldnt-hide</guid>
            <pubDate>Sat, 23 May 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[Diez gaps latentes aflorados en un solo polish Charter, y el anti-patrón que se ganó un nombre]]></description>
            <content:encoded><![CDATA[<p><em>Un polish Charter que iba a ser limpieza cosmética afloró diez gaps de producción en seis horas — incluyendo dos features que estaban shippeadas a <code>main</code> y nunca habían funcionado durante diez días. El anti-patrón obtuvo nombre, el patrón se documentó como <code>fw-4.18.0</code>, y el helper de CLI se difirió a propósito.</em></p>
<!-- -->
<blockquote>
<p><em>"Lo primero que el polish Charter intentó — bootear <code>./sentinel</code> desde <code>main</code> para correr el smoke de §5 — falló con dos panics distintos."</em></p>
</blockquote>
<p>Así abrió el Issue <a href="https://github.com/StrangeDaysTech/straymark/issues/199" target="_blank" rel="noopener noreferrer" class="">#199</a> el 22 de mayo, presentado por el adopter Sentinel como RFC. Para cuando el thread cerró cinco actualizaciones de comentario después, la cuenta había crecido de dos a diez. El polish Charter — el Charter de cierre de Etapa 2, planeado como un docket de auditorías WCAG y verificación del quickstart — había pasado seis horas haciendo otra cosa: cazando una clase de regresión latente que ninguna de las suites de tests per-Charter de los ocho Charters previos había cazado, y que ninguna de ellas <em>podía</em> haber cazado dado cómo estaban escritas.</p>
<p>Este post es la reconstrucción de por qué ocurrió, qué forma recurrente terminó habiendo debajo, y la decisión deliberada en el PR <a href="https://github.com/StrangeDaysTech/straymark/pull/200" target="_blank" rel="noopener noreferrer" class="">#200</a> de <strong>nombrar el anti-patrón pero todavía no fabricar tooling para él</strong>. El ciclo le es familiar a quien siguió los posts previos sobre <a class="" href="https://straymark.dev/es/blog/emergent-observation-design">observación emergente</a> y <a class="" href="https://straymark.dev/es/blog/pattern-1-and-pattern-2-chain-evolution">evolución de cadenas</a> — este es el tercer patrón en dos semanas que cristaliza vía el mismo arco: aflorar en N=1, nombrar el meta, diferir el tooling cross-proyecto hasta que N=2 lo valide.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="los-dos-casos-que-pesaron">Los dos casos que pesaron<a href="https://straymark.dev/es/blog/what-the-binary-couldnt-hide#los-dos-casos-que-pesaron" class="hash-link" aria-label="Enlace directo al Los dos casos que pesaron" title="Enlace directo al Los dos casos que pesaron" translate="no">​</a></h2>
<p>De los diez gaps que la sesión de polish afloró, ocho eran o bien deterioro ambiental de dependencias (un upgrade de <code>huma</code> introdujo un panic en parámetros <code>*string</code>; Go 1.22 endureció la semántica de wildcards de <code>http.ServeMux</code>) o bien drift del runbook (env vars faltantes en §boot, recetas de smoke que mezclaban modos mutuamente excluyentes, afirmaciones sobre el stdout de un fake provider que el fake nunca escribió). Cada uno merece un fix. Ninguno reescribe el manual.</p>
<p>Los dos que sí reescribieron el manual son distintos. Comparten forma.</p>
<p><strong>US3 Preference Center, shippeado el 12 de mayo.</strong> Cuando los recipients de un correo enviado por Sentinel hacen click en el link tipo unsubscribe del footer, aterrizan en una URL JWT-in-path como <code>/preferences/&lt;token&gt;</code>. El handler es público-por-contrato a propósito: el JWT <em>es</em> la auth; no se espera un header <code>Authorization</code>. El doc-comment del handler lo decía. El test de integración, escrito en <code>humatest</code>, montaba el handler directamente a través del adapter de testing y confirmaba: dado un JWT válido en el path, el handler devuelve el HTML correcto. CI pasó. La feature se shipeó a <code>main</code>.</p>
<p>Lo que nunca pasó: nada que ejerciera la cadena de middleware de producción enfrente de ese handler. <code>internal/core/middleware/auth.go</code> tiene una lista <code>publicPrefixes</code> de prefijos de ruta que evaden el check de <code>Authorization</code>. <code>/preferences/</code> no estaba en ella. Durante diez días, cada recipient que hizo click en un link de unsubscribe recibió un <code>401 missing authorization header</code> del middleware antes de que el request alcanzara nunca al handler que sabía que no debía esperarlo. El Preference Center era alcanzable en tests, inalcanzable en producción.</p>
<p><strong>Instrumentos de observabilidad OTel del pipeline de envío, shippeados la misma semana.</strong> Ocho metric instruments — counters, histograms, gauges — declarados en <code>internal/core/metrics/commshub.go</code>, registrados con el meter de OpenTelemetry al boot. El <code>Constitution Check §IV</code> del Charter declaró formalmente satisfecha la compuerta de observabilidad FR-039..042: la capa de API era correcta, los registros pasaban, los dashboards estaban planeados. Siete de esos ocho instrumentos tenían <strong>cero call sites de <code>.Add()</code> / <code>.Record()</code> en todo el módulo commshub</strong>. Declarados, registrados, nunca invocados. Los dashboards que ops construyó encima de esas series llevaban diez días recibiendo cero datos. El smoke manual del polish Charter — bootear un OTel Collector, generar unos cuantos sends, grep del output del collector buscando los nombres FR-039..042 — afloró esto al instante.</p>
<p>Ninguno de los dos casos es exótico. Ninguno es un bug duro. Ambos son instancias del mismo error mecánico: un artefacto se declaró en un lugar, y la implementación que se suponía que lo cableara vivía en otro lugar, y nada en el codebase ni en CI correlacionaba los dos.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="el-nombre-que-el-anti-patrón-pedía">El nombre que el anti-patrón pedía<a href="https://straymark.dev/es/blog/what-the-binary-couldnt-hide#el-nombre-que-el-anti-patr%C3%B3n-ped%C3%ADa" class="hash-link" aria-label="Enlace directo al El nombre que el anti-patrón pedía" title="Enlace directo al El nombre que el anti-patrón pedía" translate="no">​</a></h2>
<p>Un nombre importa cuando la misma forma aparece suficientes veces como para merecer uno. Para la tercera actualización del comentario en #199, el autor de Sentinel había contado cuatro subclases del mismo error subyacente:</p>






























<table><thead><tr><th>Sitio de declaración</th><th>Sitio de cableado</th><th>Verificación mecánica</th></tr></thead><tbody><tr><td>env var documentada en el runbook operativo</td><td><code>os.Getenv(...)</code> (o equivalente del stack) en código</td><td>cada env var documentada tiene al menos un consumidor</td></tr><tr><td>metric instrument declarado en un paquete de métricas</td><td>call site <code>.Record()</code> / <code>.Add()</code> en código de handler o worker</td><td>cada instrument declarado se registra al menos una vez</td></tr><tr><td>URL referenciada desde HTML renderizado/embebido (<code>&lt;script src=...&gt;</code>, <code>&lt;link href=...&gt;</code>)</td><td>ruta registrada en la misma superficie de API</td><td>cada <code>src=</code>/<code>href=</code> en HTML servido resuelve a una ruta registrada</td></tr><tr><td>ruta marcada pública-por-contrato (doc-comment, marker dedicado)</td><td>entrada en la lista de prefijos públicos del middleware de auth</td><td>cada handler público-por-contrato tiene una entrada de prefijo equivalente</td></tr></tbody></table>
<p>El unificador — el one-liner con el que abre el nuevo doc de gobernanza — es:</p>
<blockquote>
<p><em>Cada artefacto de superficie declarado tiene al menos un sitio de cableado alcanzable desde un request real.</em></p>
</blockquote>
<p>El nombre del anti-patrón, que aterriza canónicamente en <code>dist/.straymark/00-governance/POLISH-CHARTER-PATTERN.md</code>, es <strong>Declaración de superficie sin cableado.</strong> Ese es el deliverable. El polish Charter es el vehículo de descubrimiento, no la tesis.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="por-qué-los-tests-de-integración-omiten-esto-sistemáticamente">Por qué los tests de integración omiten esto sistemáticamente<a href="https://straymark.dev/es/blog/what-the-binary-couldnt-hide#por-qu%C3%A9-los-tests-de-integraci%C3%B3n-omiten-esto-sistem%C3%A1ticamente" class="hash-link" aria-label="Enlace directo al Por qué los tests de integración omiten esto sistemáticamente" title="Enlace directo al Por qué los tests de integración omiten esto sistemáticamente" translate="no">​</a></h2>
<p>Esta parte vale la pena trabajarla porque le da forma al resto del post. El modo de falla común a las cuatro subclases es que el harness estándar de tests de integración — <code>humatest.NewTestAdapter</code> en Go, el equivalente en TypeScript, Python, Rust — monta los handlers <em>directamente</em> vía la API de testing. El handler bajo prueba está correctamente cableado por el fixture. El paso de composición de producción — donde el registro de rutas se encuentra con la cadena de middleware se encuentra con el inventario de env vars se encuentra con la tabla de assets embebidos — es lo que está roto. La luz verde de CI es genuina respecto a lo que afirma: el handler devuelve la respuesta correcta dado el request correcto. No dice nada sobre si el request puede alcanzar el handler en producción, o sobre si el artefacto del que el handler depende fue alguna vez cableado al runtime.</p>
<p>Hay una tentación de leer esto como una crítica a <code>humatest</code>. No lo es. <code>humatest</code> (y sus equivalentes) está haciendo exactamente lo que fue diseñado para hacer: dejar que pruebes la lógica del handler en aislamiento, rápido, sin parar todo el árbol de composición. Ese aislamiento es una feature. El costo del aislamiento es lo que acabamos de nombrar — y el costo solo se vuelve visible cuando algo fuera del aislamiento aflora una divergencia. El polish Charter es el método más barato para aflorar esa divergencia, porque hace lo que ningún fixture de test hace: bootea el binario real y corre la receta operativa documentada real contra él.</p>
<p>Esta es la afirmación load-bearing del nuevo pattern doc. No que los polish Charters sean valiosos por razones cosméticas. Que son <strong>el único lugar</strong> donde la composición de producción se ejerce end-to-end contra una especificación externamente legible (el runbook operativo). Si tratas el polish Charter como limpieza cosmética, también tratas esa capacidad de aflorar como cosmética. Los datos de Sentinel argumentan lo opuesto.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="la-decisión-b-no-b">La decisión: B′, no B<a href="https://straymark.dev/es/blog/what-the-binary-couldnt-hide#la-decisi%C3%B3n-b-no-b" class="hash-link" aria-label="Enlace directo al La decisión: B′, no B" title="Enlace directo al La decisión: B′, no B" translate="no">​</a></h2>
<p>El RFC proponía tres opciones. La decisión en el PR #200 fue ninguna de ellas tal como estaban formuladas — llamémosla B′. Vale la pena decir por qué, porque la decisión estructural pesa más de lo que parece.</p>
<p><strong>La Option B del RFC</strong> pedía un pattern doc bajo <code>docs/patterns/</code>. Ese directorio no existe en StrayMark hoy, y crearlo habría partido la convención de documentación del proyecto. Los patterns empíricos que ya viven en el canon — <code>FOLLOW-UPS-BACKLOG-PATTERN.md</code>, <code>CHARTER-CHAIN-EVOLUTION.md</code>, <code>EMERGENT-OBSERVATION-DESIGN.md</code>, <code>SPECKIT-CHARTER-BRIDGE.md</code> — todos viven en <code>dist/.straymark/00-governance/</code>. Comparten una infraestructura de mirror i18n (cada doc de gobernanza tiene hermanos en inglés, español y chino simplificado). Agregar una tercera superficie de documentación habría multiplicado el overhead de i18n y desparramado los patterns del proyecto entre dos hogares. Mantener el nuevo doc dentro de <code>00-governance/</code> reusaba la infraestructura existente con costo marginal cero.</p>
<p><strong>La Option C del RFC</strong> pedía un helper CLI <code>straymark charter polish-checklist</code> o <code>straymark analyze declared-vs-wired</code>. El autor de Sentinel ya había prototipado uno (CHARTERs 25/26/27, los tres guards preparatorios de CI) y ofrecido sembrarlo upstream. La decisión aquí fue conservadora: diferir. No porque el prototipo no sea valioso — lo es — sino porque Sentinel es N=1. Las cuatro subclases fueron las que <em>un adopter, un stack</em> afloró. La quinta, sexta y séptima subclase que el framework tendría que anticipar para shippear un CLI cross-proyecto útil aún no existen, porque ningún segundo adopter las ha empujado. Ya hemos recorrido este camino. <a href="https://github.com/StrangeDaysTech/straymark/blob/main/dist/.straymark/00-governance/FOLLOW-UPS-BACKLOG-PATTERN.md" target="_blank" rel="noopener noreferrer" class=""><code>FOLLOW-UPS-BACKLOG-PATTERN.md</code></a> shippeó como v0 en <code>fw-4.10.0</code> y vive ahí desde hace mes y medio, esperando que un segundo adopter lo valide antes de graduarse a un subcomando <code>straymark followups</code>. La misma compuerta aplica aquí. Las <code>## Open questions</code> del nuevo doc lo dicen explícitamente: "Cristalización como subcomando CLI <code>straymark analyze declared-vs-wired</code> … Gate: N=2 adopters."</p>
<p><strong>B′ es lo que aterrizó.</strong> Un nuevo governance pattern doc en la ubicación canónica, en tres idiomas. Un séptimo bullet de <code>Format conventions</code> en el template de Charter apuntando a los autores hacia él cuando cierran una Etapa o Fase <code>Polish</code> de SpecKit. Una fila en la tabla <code>## Patterns</code> del QUICK-REFERENCE. Un bump <code>fw-4.18.0</code> con la cascada de footers a través de unos treinta docs. Ningún subcomando CLI. Ningún nuevo campo de frontmatter. Ningún cambio de schema. El anti-patrón tiene un nombre; el ritual de descubrimiento tiene un doc; el tooling espera.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="el-arco-que-se-repite">El arco que se repite<a href="https://straymark.dev/es/blog/what-the-binary-couldnt-hide#el-arco-que-se-repite" class="hash-link" aria-label="Enlace directo al El arco que se repite" title="Enlace directo al El arco que se repite" translate="no">​</a></h2>
<p>Hace tres semanas, el patrón de backlog de follow-ups cristalizó vía el mismo arco: un adopter afloró una necesidad, el patrón se nombró en v0, el helper CLI se difirió. Hace dos semanas, los patrones de evolución de cadena cristalizaron: Pattern 1 (pre-declare SpecKit refresh) y Pattern 2 (post-close audit-driven Batch N.4), aflorados desde el mismo adopter Sentinel, nombrados en <code>fw-4.16.0</code>, con <code>straymark charter refresh-suggest</code> como helper blando en vez de gate duro. Hace una semana, el meta — <code>EMERGENT-OBSERVATION-DESIGN.md</code> — codificó qué hacía posibles esas observaciones de entrada: cross-referencing formal más permiso cultural. Esta semana, este patrón.</p>
<p>Son cuatro cristalizaciones en un mes, todas desde el mismo adopter, todas siguiendo la misma forma: <strong>aflorar en N=1 → nombrar el meta → fabricar tooling solo después de N=2</strong>. La tentación cuando un patrón aflora vívidamente — y diez gaps de producción en seis horas es vívido — es saltearse el nombre e ir directo al tooling. La disciplina es lo opuesto. El nombre hace la mayor parte del trabajo. El tooling, cuando llega, está parametrizado por lo que al menos dos adopters han aflorado; construido sobre N=1, es una extrapolación de un stack y los modos de falla de un equipo, y tiende a osificar esas elecciones como defaults del framework que no generalizan.</p>
<p>Hay una pieza de esta iteración que sí es genuinamente nueva y vale la pena destacar. El nuevo pattern doc nombra una predicción falsable que el autor de Sentinel ya se comprometió a publicar: el polish Charter de la próxima Etapa, ejecutado contra los tres guards preparatorios de CI que acaban de aterrizar en CHARTERs 25/26/27 de Sentinel, debería aflorar aproximadamente 80% menos gaps. Si esa predicción se sostiene, el caso para graduar la Option C de "open question" a "subcomando CLI" obtiene respaldo cuantitativo. Si falla — si el siguiente polish Charter sigue aflorando diez gaps pero en una quinta subclase no anticipada — la falla en sí misma es el siguiente data point, y reescribe el spec antes de fabricar tooling. Cualquiera de los dos resultados es útil. Ninguno se ha observado aún. Esperamos.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="una-nota-sobre-lo-que-deliberadamente-no-se-hizo">Una nota sobre lo que deliberadamente no se hizo<a href="https://straymark.dev/es/blog/what-the-binary-couldnt-hide#una-nota-sobre-lo-que-deliberadamente-no-se-hizo" class="hash-link" aria-label="Enlace directo al Una nota sobre lo que deliberadamente no se hizo" title="Enlace directo al Una nota sobre lo que deliberadamente no se hizo" translate="no">​</a></h2>
<p>No hay campo <code>phase: polish</code> en el frontmatter de Charter. No hay <code>straymark charter polish-checklist &lt;ID&gt;</code>. No hay analyzer automatizado escaneando código Go (ni de ningún otro lenguaje) por símbolos declarados-pero-no-cableados. El pattern doc lista cada una de esas como candidata de evolución, gated explícitamente en N=2 o en el retrospectivo post-Etapa-3. Ninguna está presente en <code>fw-4.18.0</code>.</p>
<p>Esto es intencional y vale la pena decirlo en voz alta, porque la reacción natural ante un hallazgo vívido es sobre-construir la respuesta. Cada una de esas postergaciones intercambia exhaustividad de corto plazo por portabilidad de largo plazo. Un campo de frontmatter compromete al framework con un vocabulario que el próximo adopter puede no compartir. Un helper CLI compromete al framework con un runtime que refleja los modos de falla de un stack específico. Un analyzer compromete al framework con escanear un lenguaje cuyas convenciones pueden divergir de las del próximo adopter. Ninguno de esos compromisos debería hacerse con la señal de un solo dominio, por más limpia que sea la señal. El pattern doc en sí mismo puede revisarse; un subcomando CLI no puede desshipearse sin romper a los adopters.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="qué-te-sugeriría-mirar-si-llegaste-hasta-acá">Qué te sugeriría mirar, si llegaste hasta acá<a href="https://straymark.dev/es/blog/what-the-binary-couldnt-hide#qu%C3%A9-te-sugerir%C3%ADa-mirar-si-llegaste-hasta-ac%C3%A1" class="hash-link" aria-label="Enlace directo al Qué te sugeriría mirar, si llegaste hasta acá" title="Enlace directo al Qué te sugeriría mirar, si llegaste hasta acá" translate="no">​</a></h2>
<p>Si operás un codebase con tests de integración basados en mock adapter — que es la mayoría de los codebases — podés correr un ejercicio interno útil sin adoptar nada de StrayMark. Elegí la feature más reciente que tu equipo shipeó que tenga tanto (a) una declaración del lado de docs (env vars, specs OpenAPI, HTML embebido, metric instruments) como (b) un sitio de cableado que viva en un archivo distinto. Booteá el binario desde una shell limpia. Corré la receta operativa del runbook end-to-end. Si funciona al primer intento, tu codebase aún no tiene la deuda latente que este patrón caza — o sí la tiene y tuviste suerte en este caso. Si no funciona, contá los gaps. El número es la calibración que necesitás para saber si el ritual de polish-Charter-como-detección-de-deuda valdría su overhead en tu proyecto.</p>
<p>Si adoptaste StrayMark y estás cerrando una Etapa con handlers testeados a través de adapters estilo <code>humatest</code>, el nuevo pattern doc tiene las cuatro verificaciones de subclase scoped para vos. Presupuestá el polish Charter como L, no XS o S. Esperá Charters emergentes de follow-on, no scope creep de limpieza residual. Leé <a href="https://github.com/StrangeDaysTech/straymark/blob/main/dist/.straymark/00-governance/POLISH-CHARTER-PATTERN.md" target="_blank" rel="noopener noreferrer" class=""><code>POLISH-CHARTER-PATTERN.md</code></a> antes de scopear el trabajo, no después.</p>
<p>Y si sos adopter en un stack distinto a Go — TypeScript, Python, Rust, Elixir — las cuatro subclases son agnósticas de lenguaje, pero la forma concreta de verificación no lo es. Aflorar una quinta o sexta subclase en tu stack es exactamente la señal de segundo-adopter que el patrón necesita para graduarse de v0. El camino de "observación interesante en tu proyecto" a "nombrada en el canon de StrayMark" corre por el mismo canal por donde corrió #199: abrir un issue. El costo de abrirlo es bajo; el costo de dejar el patrón subvalidado es real.</p>
<hr>
<p><em>StrayMark <code>fw-4.18.0</code> — Issue <a href="https://github.com/StrangeDaysTech/straymark/issues/199" target="_blank" rel="noopener noreferrer" class="">#199</a> · PR <a href="https://github.com/StrangeDaysTech/straymark/pull/200" target="_blank" rel="noopener noreferrer" class="">#200</a> · tag <a href="https://github.com/StrangeDaysTech/straymark/releases/tag/fw-4.18.0" target="_blank" rel="noopener noreferrer" class=""><code>fw-4.18.0</code></a>. Anclas de Sentinel: <a href="https://github.com/StrangeDaysTech/sentinel/pull/93" target="_blank" rel="noopener noreferrer" class=""><code>AIDEC-2026-05-22-001</code></a> · <a href="https://github.com/StrangeDaysTech/sentinel/pull/94" target="_blank" rel="noopener noreferrer" class="">PR de CHARTERs 25/26/27</a>.</em></p>
<p><em>Este documento fue elaborado con asistencia de herramientas de IA generativa (Claude 4.7); toda la responsabilidad del contenido recae en el autor humano.</em></p>]]></content:encoded>
            <category>straymark</category>
            <category>charters</category>
            <category>governance</category>
            <category>polish-charter</category>
            <category>sentinel</category>
            <category>anti-patron</category>
        </item>
        <item>
            <title><![CDATA[El día que el agente vio algo que nadie le pidió ver]]></title>
            <link>https://straymark.dev/es/blog/emergent-observation-design</link>
            <guid>https://straymark.dev/es/blog/emergent-observation-design</guid>
            <pubDate>Sat, 16 May 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[Cómo nombrar una propiedad de diseño que ya estaba haciendo su trabajo en silencio]]></description>
            <content:encoded><![CDATA[<p><em>Un agente señaló un spec desactualizado sin que nadie se lo pidiera. La reconstrucción de esa mañana y la propiedad de diseño que lo hace posible — codificada a posteriori como Principio #8 de StrayMark.</em></p>
<!-- -->
<blockquote>
<p><em>"Hola, ¿ya tratamos el Issue #153?"</em></p>
</blockquote>
<p>Así empezó la conversación, hoy 16 de mayo a la mañana. Una pregunta corta, casi de housekeeping, antes de meterme en otra cosa. La respuesta era no — el Issue #153 estaba abierto a propósito, esperando un segundo dominio que ejercitara la mecánica antes de cristalizarla (Principio #12 de StrayMark, validación contra un segundo dominio antes de canonizar). Pero la pregunta abrió otra puerta, y al final de esa conversación había codificado una propiedad de diseño del framework que llevaba meses funcionando sin nombre, señalada por un episodio de hace apenas dos días.</p>
<p>Este post es la reconstrucción del arco, porque vale la pena guardarla. No por el resultado — un nuevo doc canónico, un Principio #8, un PR ya fusionado — sino por el mecanismo que reveló. StrayMark tiene un proyecto humano detrás: que el desarrollo asistido por agentes no se nos escape de las manos a los ingenieros que somos responsables del software que producimos. Y este episodio expuso una propiedad concreta del diseño que empuja en esa dirección.</p>
<p>Aclaración de oficio: StrayMark se prueba primero en mis propios proyectos. Sentinel es uno de ellos — privado, pero su interacción con StrayMark queda documentada en los Issues públicos del repo de StrayMark, así que el contexto es vinculable. Soy autor y primer adopter del framework. El Principio #12 me obliga a esperar un segundo dominio antes de declarar canónica cualquier mecánica nueva; pero el primero soy yo, y este post da cuenta de eso sin pudor.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="el-incidente-un-agente-que-señaló-lo-que-nadie-le-pidió-señalar">El incidente: un agente que señaló lo que nadie le pidió señalar<a href="https://straymark.dev/es/blog/emergent-observation-design#el-incidente-un-agente-que-se%C3%B1al%C3%B3-lo-que-nadie-le-pidi%C3%B3-se%C3%B1alar" class="hash-link" aria-label="Enlace directo al El incidente: un agente que señaló lo que nadie le pidió señalar" title="Enlace directo al El incidente: un agente que señaló lo que nadie le pidió señalar" translate="no">​</a></h2>
<p>El <strong>14 de mayo, hace dos días</strong>, en Sentinel, un agente trajo a mi atención una observación que no le había pedido. Estaba a punto de ayudarme a completar el CHARTER-18 — una pieza de trabajo concreta dentro de una cadena ya larga — y antes de poner una línea de código dijo, en esencia:</p>
<blockquote>
<p><em>Hay un problema. El <code>specs/002-commshub/plan.md</code> se congeló el 21 de abril. Desde entonces han pasado siete Charters consecutivos, y a lo largo de los AILOGs de esa cadena hay doce aprendizajes empíricos no reflejados en el plan que afectan materialmente el alcance de US5. Si completamos CHARTER-18 leyendo el plan desactualizado, el próximo ciclo de auditoría va a remediar divergencias atómicamente pre-close — con aproximadamente 50% de probabilidad de al menos un hallazgo crítico o alto por herencia de premisa rancia.</em></p>
</blockquote>
<p>Y citó los AILOGs específicos por ID. Y las referencias de código concretas.</p>
<p>Nadie le pidió ese análisis. No había un disparador configurado. No había un comando CLI cuyo propósito fuera producir esa salida. El agente estaba allí para ayudarme con la siguiente tarea, no para auditar el estado del proyecto. Pero al posicionarse para esa siguiente tarea, vio una divergencia entre dos fuentes que la documentación StrayMark conecta explícitamente, y eligió señalarla antes de proceder.</p>
<p>Abrí el Issue <a href="https://github.com/StrangeDaysTech/straymark/issues/150" target="_blank" rel="noopener noreferrer" class="">#150</a> ese mismo día por la tarde como RFC, y entre las 17:00 y la noche se discutió y aterrizó la disciplina manual de spec-refresh en <code>fw-4.14.3</code>. Al día siguiente, <strong>15 de mayo</strong>, levanté el Issue <a href="https://github.com/StrangeDaysTech/straymark/issues/156" target="_blank" rel="noopener noreferrer" class="">#156</a> para llevar upstream los dos patrones que el ejercicio había revelado: un <em>pre-declare SpecKit refresh</em> y una <em>post-close Batch N.4 amendment</em>. Para la madrugada del <strong>16 de mayo</strong> estaban canonizados en <code>fw-4.16.0</code> como <code>CHARTER-CHAIN-EVOLUTION.md</code>, con telemetría dedicada y un helper CLI (<code>straymark charter refresh-suggest</code>). El comportamiento se reprodujo, los patrones se cristalizaron, ciclo cerrado.</p>
<p>Pero cuando me senté esa misma mañana del 16 a abrir la conversación con el Issue #153 — <em>"¿ya tratamos esto?"</em> — y me devolví la pregunta inversa — <em>"un momento, ¿qué fue lo que hizo posible esa observación en primer lugar?"</em> — me di cuenta de que el ciclo había cerrado solamente a medias. Lo que se codificó en <code>fw-4.16.0</code> fue la <strong>aplicación</strong> del patrón. Lo que faltaba codificar era el <strong>mecanismo</strong> que la produjo.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="la-pregunta-humana-dicha-con-palabras-técnicas">La pregunta humana, dicha con palabras técnicas<a href="https://straymark.dev/es/blog/emergent-observation-design#la-pregunta-humana-dicha-con-palabras-t%C3%A9cnicas" class="hash-link" aria-label="Enlace directo al La pregunta humana, dicha con palabras técnicas" title="Enlace directo al La pregunta humana, dicha con palabras técnicas" translate="no">​</a></h2>
<p>Se la formulé así, en la conversación con el agente que generó este post:</p>
<blockquote>
<p><em>Me resultó algo sorpresivo el comportamiento del agente que se percató de ese conocimiento acumulado que, de no aplicarse, ocasionaría problemas con la implementación del Charter 18. Es decir, que no era una tarea que se le pidió analizar, ni fue el resultado de la activación de un disparador de prompt, y me parece que fue gracias a la documentación StrayMark. Quisiera que ahondáramos más en cómo ocurrió esto, que creo que es positivo, de forma en que podamos aprovechar la experiencia y engancharla en el comportamiento habitual de StrayMark, este patrón emergente que provino del agente y su relación con la documentación generada, fue muy interesante.</em></p>
</blockquote>
<p>Lo que estoy pidiendo ahí no es implementar un feature. Es entender un mecanismo para poder reproducirlo. La diferencia es importante. Cuando uno pide implementar algo, el camino es claro: spec → tasks → código. Cuando pide entender por qué algo funcionó, el camino es más raro: hay que diagnosticar un sistema funcional, identificar qué piezas lo hicieron funcionar, y separar lo accidental de lo estructural.</p>
<p>Hay una urgencia particular en este tipo de pregunta cuando uno está construyendo herramientas para colaborar con agentes de IA. Porque si lo que funcionó fue accidente, el próximo agente — o la próxima versión del mismo agente — puede no reproducirlo. Si lo que funcionó fue estructura, entonces se puede preservar deliberadamente. La diferencia entre las dos cosas, para un proyecto que pretende dar a los ingenieros control sobre el desarrollo asistido por IA, es la diferencia entre suerte y diseño.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="la-auditoría-qué-piezas-de-straymark-hicieron-posible-la-observación">La auditoría: ¿qué piezas de StrayMark hicieron posible la observación?<a href="https://straymark.dev/es/blog/emergent-observation-design#la-auditor%C3%ADa-qu%C3%A9-piezas-de-straymark-hicieron-posible-la-observaci%C3%B3n" class="hash-link" aria-label="Enlace directo al La auditoría: ¿qué piezas de StrayMark hicieron posible la observación?" title="Enlace directo al La auditoría: ¿qué piezas de StrayMark hicieron posible la observación?" translate="no">​</a></h2>
<p>Le pedí a un agente que mapeara sistemáticamente la documentación StrayMark con tres preguntas concretas:</p>
<ol>
<li class="">¿Qué mecanismos documentales conectan fuentes explícitamente entre sí? (Frontmatter, secciones canónicas, IDs estables, comandos CLI que cruzan fuentes.)</li>
<li class="">¿Dónde le da la documentación al agente <em>permiso explícito</em> para señalar cosas más allá de la tarea pedida?</li>
<li class="">¿Qué pares de fuentes existen, además del que originó este caso, que podrían producir observaciones emergentes similares si la infraestructura está presente?</li>
</ol>
<p>El reporte vino estructurado, con archivo:línea para cada hallazgo. Lo importante no fueron los detalles individuales (frontmatter con <code>originating_charter:</code>, secciones <code>§Risk: R&lt;N&gt;</code>, convenciones de IDs estables, comandos como <code>charter drift</code>) sino el patrón que emergió al verlos en conjunto. Dos propiedades coexistían consistentemente:</p>
<p><strong>Propiedad 1: cross-referencing estructural obligatorio.</strong> Cada tipo de documento tiene <em>campos obligatorios</em> y <em>secciones canónicas</em> que declaran, en la propia estructura del documento, a qué otros documentos apunta. Cuando un agente lee un AILOG, no tiene que adivinar a qué Charter pertenece — el <code>originating_charter:</code> se lo dice. Cuando ve un riesgo, no es una observación en prosa libre — es una entrada <code>R&lt;N&gt;</code> en una sección canónica, contable. Cuando el spec apunta a Charters, lo hace formalmente; cuando los Charters apuntan a AILOGs, igual. Es un grafo de enlaces explícito que el agente puede triangular sin trabajo creativo.</p>
<p><strong>Propiedad 2: permiso cultural sin control bloqueante.</strong> AGENT-RULES §6 le dice al agente: <em>"Be Proactive — Identify potential risks, Suggest improvements when evident, Alert about technical debt"</em>. PRINCIPLES §2 le dice: <em>"Not hide relevant information"</em>. Y críticamente, AGENT-RULES §3 le da autonomía para <em>crear</em> documentos (AILOG, AIDEC, TDE) sin pre-aprobación del operador. El operador retiene la priorización, no la creación. El agente no tiene que pedir permiso para señalar algo: señalarlo es ejecución de una regla, no juicio de valor.</p>
<p>Lo interesante es que ninguna de las dos propiedades por sí sola produce el comportamiento. Si tuvieras solamente enlaces formales (Propiedad 1) sin permiso cultural, tendrías un corpus consultable que ningún agente se atreve a consultar proactivamente. Si tuvieras solamente permiso cultural (Propiedad 2) sin estructura, tendrías señales vagas — <em>"creo que algo podría estar mal en algún lado"</em> — que los operadores no podemos accionar.</p>
<p>Combinadas, producen algo que merece nombre propio: el agente externalizó <em>"¿debo decir algo?"</em> como <em>"¿existe una sección canónica donde esto encaja?"</em>. Si la respuesta es sí, señalarlo deja de ser una decisión emocional y se vuelve ejecución mecánica. El costo de señalar baja porque el destino — la sección canónica — ya existe.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="por-qué-esto-importa-más-allá-de-straymark">Por qué esto importa más allá de StrayMark<a href="https://straymark.dev/es/blog/emergent-observation-design#por-qu%C3%A9-esto-importa-m%C3%A1s-all%C3%A1-de-straymark" class="hash-link" aria-label="Enlace directo al Por qué esto importa más allá de StrayMark" title="Enlace directo al Por qué esto importa más allá de StrayMark" translate="no">​</a></h2>
<p>Estamos en un momento donde los agentes de IA pueden escribir código tan rápido como pensamos, y la pregunta de cómo <em>no perder el control</em> del proceso es genuinamente urgente. No es una pregunta apocalíptica — es una pregunta operativa, de oficio, de personas que estamos construyendo software ahora mismo y tenemos que entregar. Lo evidencia el ritmo mismo de este episodio: del diagnóstico del agente al meta-patrón canonizado pasaron menos de <strong>72 horas</strong>. Esa velocidad es ganancia, pero también es la razón por la cual los mecanismos de visibilidad importan tanto.</p>
<p>La respuesta dominante en la industria hoy es alguna variante de <em>prompts más estrictos, más reglas en el contexto, más gates en CI</em>. Esos enfoques son válidos pero tienen una característica que vale la pena nombrar: convierten al agente en algo más cercano a un trabajador que ejecuta órdenes en pipelines verificables. Eso resuelve la confiabilidad pero al costo de la observación emergente. Un agente que solo hace lo que se le ordena no va a señalar algo que nadie le pidió señalar, por buen razonamiento que tenga.</p>
<p>Lo que el episodio de Sentinel mostró es una respuesta diferente, complementaria: <strong>construir el aparato documental de tal forma que las divergencias importantes sean estructuralmente visibles, y dar al agente permiso cultural para señalarlas sin pedir aprobación.</strong> Eso preserva la observación emergente como propiedad del sistema, no como suerte de qué tan bueno sea el agente o qué tan extenso sea el prompt.</p>
<p>Hay algo casi taoísta en esta postura: no le decimos al agente qué buscar; construimos un entorno donde lo que hay que ver es visible. La pareja "estructura visible + permiso para nombrar" hace el trabajo. El agente se vuelve, parafraseando a algunos colegas, un <em>honest broker</em> entre la documentación viva y el estado del código.</p>
<p>Y esto es lo que el proyecto humano detrás de StrayMark persigue, aunque rara vez se diga con esas palabras: que el cambio vertiginoso del desarrollo asistido por IA no nos arroje a un mundo donde los ingenieros perdemos visibilidad sobre lo que se está construyendo. La visibilidad no se preserva con más controles burocráticos; se preserva diseñando el entorno donde el agente trabaja para que lo importante sea naturalmente visible. El ingeniero no se vuelve un revisor de Pull Requests interminables — se vuelve un priorizador de observaciones que el agente trae estructuradas y nombradas.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="lo-que-hicimos-al-respecto">Lo que hicimos al respecto<a href="https://straymark.dev/es/blog/emergent-observation-design#lo-que-hicimos-al-respecto" class="hash-link" aria-label="Enlace directo al Lo que hicimos al respecto" title="Enlace directo al Lo que hicimos al respecto" translate="no">​</a></h2>
<p>Con el diagnóstico claro, la pregunta era cómo engancharlo al comportamiento habitual de StrayMark sin matar la calidad emergente. Esta tensión es real: cada vez que conviertes un comportamiento espontáneo en obligación, lo conviertes en otra cosa. Una regla dura puede ser robusta, pero también puede generar resistencia en el agente o falsa señal cuando se activa fuera de contexto.</p>
<p>La decisión fue conservadora: <strong>nombrar el meta-patrón, no obligar su uso.</strong></p>
<p>Concretamente, en el PR <a href="https://github.com/StrangeDaysTech/straymark/pull/160" target="_blank" rel="noopener noreferrer" class="">#160</a> que salió como <code>fw-4.17.0</code>:</p>
<ul>
<li class="">
<p>Un nuevo doc canónico — <code>EMERGENT-OBSERVATION-DESIGN.md</code> — articula la propiedad de diseño con sus dos componentes, presenta el caso empírico de Sentinel como ancla, y construye una <em>pirámide de instancias</em>: el meta-patrón en la cima, y abajo todas las aplicaciones que ya estaban canonizadas (Pattern 1 y Pattern 2 de la chain evolution; charter drift; follow-ups backlog drift; escalación TDE-vs-<code>R&lt;N&gt;</code>; audit checkpoint externo). Lo que antes parecían patrones ad hoc se revelan como aplicaciones del mismo principio subyacente. Esta visualización por sí sola vale la pena: cuando ves siete cosas que parecían distintas y de pronto reconoces que comparten una misma forma, el framework gana coherencia interna sin haber añadido nada.</p>
</li>
<li class="">
<p>Un nuevo Principio #8 — <em>Cross-Source Dissonance Surfacing</em> — en <code>PRINCIPLES.md</code>. Es la regla cultural condensada en cinco líneas. El agente la lee al incorporarse al proyecto y la aplica recursivamente.</p>
</li>
<li class="">
<p>Una expansión a <code>AGENT-RULES.md §6 "Be Proactive"</code> con ejemplos concretos de divergencia a vigilar: spec desactualizado, R<n> acumulados sin escalar a TDE, ADR contradicho por la implementación, follow-ups cruzando umbral del backlog pattern, hallazgos de auditoría emergiendo post-close. No son obligaciones; son <em>ejemplos de lo que un agente proactivo notaría</em>. La diferencia es importante para preservar lo emergente.</n></p>
</li>
<li class="">
<p>Cuatro ejes abiertos identificados como gaps — lugares donde la infraestructura de cross-referencing existe parcialmente pero el patrón no está nombrado: MCARD ↔ código del modelo desplegado, SBOM ↔ lockfiles, ADR vigente ↔ implementación que la contradice, Constitution Check ↔ bump de versión del framework. Cada uno requiere validación N=1 empírica antes de cristalizar — Principio #12 aplica. Quedaron registrados en el Issue <a href="https://github.com/StrangeDaysTech/straymark/issues/161" target="_blank" rel="noopener noreferrer" class="">#161</a> como tracking RFC, esperando que un segundo dominio empuje alguno de ellos.</p>
</li>
<li class="">
<p>Anti-patrones explícitos: cómo se rompe el meta. Si un nuevo tipo de documento sale con enlaces de frontmatter opcionales, el cross-referencing desarrolla puntos ciegos. Si una sección canónica se reemplaza por prosa libre, la consultabilidad se evapora. Si se introduce control bloqueante en la creación de AILOG/AIDEC/TDE, el permiso cultural se rompe. Si la telemetría evoluciona sin preservar señales como <code>r_n_plus_one_emergent_count</code>, el feedback loop se rompe. Estos anti-patrones son una protección barata pero efectiva contra la erosión accidental: cualquier futura propuesta de cambio se puede contrastar con la lista para detectar si está regresando el meta-patrón.</p>
</li>
</ul>
<p>Todo esto, del diagnóstico al merge y el tag <code>fw-4.17.0</code> con su release publicada, ocurrió entre las 09:00 y las 04:00 del mismo día. Quince horas. Lo cual es exactamente el tipo de ritmo que el blog admite: hay que aprender a operar bajo este reloj, o el control se nos va.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="lo-que-aprendí-del-proceso">Lo que aprendí del proceso<a href="https://straymark.dev/es/blog/emergent-observation-design#lo-que-aprend%C3%AD-del-proceso" class="hash-link" aria-label="Enlace directo al Lo que aprendí del proceso" title="Enlace directo al Lo que aprendí del proceso" translate="no">​</a></h2>
<p>Tres cosas que no esperaba aprender cuando empecé respondiendo <em>"no, el Issue #153 sigue abierto"</em>:</p>
<p><strong>Primero, que codificar un meta-patrón es distinto de codificar un patrón.</strong> El meta-patrón no añade obligaciones; añade <em>vocabulario</em> y <em>visibilidad de la propiedad subyacente</em>. Esa propiedad ya estaba haciendo su trabajo; lo que faltaba era darle nombre para protegerla bajo evolución futura. Quien lee <code>EMERGENT-OBSERVATION-DESIGN.md</code> no aprende a hacer algo nuevo — aprende a <em>reconocer</em> algo que ya estaba ahí. Eso es lo que permite preservarlo deliberadamente.</p>
<p><strong>Segundo, que la propiedad emergente desaparece si se sobre-regula.</strong> Hubo un momento en la conversación donde elegí no convertir Pattern 1 en obligación dura (<em>"el agente DEBE ejecutar <code>refresh-suggest</code> antes de declarar Charter-(N+1)"</em>) y en cambio mantenerlo como recomendación más el nombramiento del meta. Esa decisión es contraintuitiva si uno viene del mundo de <em>"más controles = más confiabilidad"</em>, pero es correcta para este tipo de propiedad. La proactividad del agente es frágil: en cuanto se vuelve mandato, deja de ser proactividad. Lo que escala es el motor cultural ("Be Proactive") más los enlaces estructurales, no la lista de obligaciones específicas.</p>
<p><strong>Tercero, que el aparato documental que construimos para los agentes también nos está educando a los humanos.</strong> Cuando vi los siete patrones dispersos en distintos docs de governance y los reconocí como instancias del mismo meta, entendí algo sobre StrayMark que no había entendido antes — y StrayMark soy yo mismo construyéndolo a lo largo de meses. El framework está revelándole cosas a su propio autor. Esa propiedad — que la documentación estructurada produce <em>insights sobre sí misma</em> cuando se la audita — es una variante doméstica de lo que el agente hace cuando señala una divergencia. Es el mismo mecanismo, aplicado a una escala distinta.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="el-proyecto-humano-detrás">El proyecto humano detrás<a href="https://straymark.dev/es/blog/emergent-observation-design#el-proyecto-humano-detr%C3%A1s" class="hash-link" aria-label="Enlace directo al El proyecto humano detrás" title="Enlace directo al El proyecto humano detrás" translate="no">​</a></h2>
<p>Hablo en serio cuando digo que StrayMark tiene un proyecto humano. No estoy construyendo un framework de gobernanza documental porque me obsesionen los campos de frontmatter. Lo construyo porque tengo la sospecha — cada vez menos especulativa — de que los próximos cinco años de la ingeniería de software van a ser una negociación constante entre la velocidad que ofrecen los agentes y la visibilidad que los ingenieros necesitamos para seguir siendo responsables del producto. Si esa negociación se pierde del lado de los agentes, terminamos en un mundo donde el código se escribe y nadie sabe por qué. Si se pierde del lado del control burocrático, terminamos sin las ganancias de productividad que justificaron el experimento.</p>
<p>El equilibrio no es teórico. Se construye con decisiones concretas: dónde poner un campo de frontmatter, qué sección debe ser canónica versus libre, cuándo dar al agente autonomía y cuándo retener priorización. Cada una de esas decisiones inclina la balanza en una dirección u otra. Y la única forma de saber si la balanza está bien es probarla — y nombrar lo que funciona cuando funciona, para que sobreviva al próximo cambio del framework.</p>
<p>El episodio del CHARTER-18, hace dos días, fue una prueba. Funcionó. Lo que escribí hoy fue darle nombre. La siguiente prueba ya tiene candidatos: MCARD, SBOM, ADR vigente vs implementación, Constitution Check ↔ framework bump. Cuatro ejes donde el meta-patrón podría reproducirse si cerramos los gaps de infraestructura. Esperaré a que un segundo dominio empuje uno empíricamente antes de codificarlo. Principio #12 — validación contra un segundo dominio antes de cristalizar — sigue siendo el guardarraíl.</p>
<p>Si estás leyendo esto y trabajas con agentes para desarrollar software, te invito a mirar tu propio aparato documental con estas dos preguntas: <em>¿qué fuentes están conectadas formalmente, con enlaces explícitos que un agente pueda triangular sin trabajo creativo?</em> y <em>¿qué tan barato es para el agente señalar algo no pedido cuando detecta una divergencia?</em> Si la respuesta a la primera pregunta es "pocas" y a la segunda es "caro", probablemente estás dejando observaciones emergentes sobre la mesa. Lo cual no es el fin del mundo — pero es exactamente lo que separa un proceso de desarrollo asistido por IA <em>bajo control humano</em> de uno que se nos va de las manos.</p>
<hr>
<p><em>StrayMark fw-4.17.0 — Issue <a href="https://github.com/StrangeDaysTech/straymark/issues/150" target="_blank" rel="noopener noreferrer" class="">#150</a> · <a href="https://github.com/StrangeDaysTech/straymark/issues/156" target="_blank" rel="noopener noreferrer" class="">#156</a> · <a href="https://github.com/StrangeDaysTech/straymark/issues/161" target="_blank" rel="noopener noreferrer" class="">#161</a> · PR <a href="https://github.com/StrangeDaysTech/straymark/pull/160" target="_blank" rel="noopener noreferrer" class="">#160</a> · tag <a href="https://github.com/StrangeDaysTech/straymark/releases/tag/fw-4.17.0" target="_blank" rel="noopener noreferrer" class=""><code>fw-4.17.0</code></a></em></p>
<p><em>Este documento fue elaborado con asistencia de herramientas de IA generativa (Claude 4.7); toda la responsabilidad del contenido recae en el autor humano.</em></p>]]></content:encoded>
            <category>straymark</category>
            <category>agentes-ia</category>
            <category>governance</category>
            <category>diseño-emergente</category>
            <category>charter</category>
            <category>sentinel</category>
        </item>
        <item>
            <title><![CDATA[Pattern 1 y Pattern 2 — chain evolution]]></title>
            <link>https://straymark.dev/es/blog/pattern-1-and-pattern-2-chain-evolution</link>
            <guid>https://straymark.dev/es/blog/pattern-1-and-pattern-2-chain-evolution</guid>
            <pubDate>Sat, 16 May 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[Cuando la disciplina deja de ser hábito y se vuelve nombre]]></description>
            <content:encoded><![CDATA[<p><em>Veintisiete horas después, la disciplina manual obtuvo dos nombres: Patrón 1 — pre-declare SpecKit refresh, y Patrón 2 — post-close audit-driven Batch N.4. El documento canónico, el schema de telemetría, los helpers del CLI — y una hora después, un meta-patrón que reabsorbe ambos hacia arriba.</em></p>
<!-- -->
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="1-veintisiete-horas-para-nombrarlos">1. Veintisiete horas para nombrarlos<a href="https://straymark.dev/es/blog/pattern-1-and-pattern-2-chain-evolution#1-veintisiete-horas-para-nombrarlos" class="hash-link" aria-label="Enlace directo al 1. Veintisiete horas para nombrarlos" title="Enlace directo al 1. Veintisiete horas para nombrarlos" translate="no">​</a></h2>
<p>El PR <a href="https://github.com/StrangeDaysTech/straymark/pull/152" target="_blank" rel="noopener noreferrer" class="">#152</a>, que cerró el episodio del Post 9, se fusionó el 14 de mayo a las 21:39 UTC. Trajo <code>fw-4.14.3</code> y los tres gates canonizados del refresh manual.</p>
<p>El PR <a href="https://github.com/StrangeDaysTech/straymark/pull/157" target="_blank" rel="noopener noreferrer" class="">#157</a> — el que este post viene a contar — se fusionó el 16 de mayo a las 00:31 UTC. Veintisiete horas después. Trajo <code>fw-4.16.0 / cli-3.14.0</code> y, con eso, dos meta-patrones nombrados:</p>
<ul>
<li class=""><strong>Pattern 1 — <em>pre-declare SpecKit refresh</em></strong>. Refrescar la spec antes de declarar el siguiente Charter en una cadena.</li>
<li class=""><strong>Pattern 2 — <em>post-close audit-driven Batch N.4</em></strong>. Amendar un Charter ya cerrado cuando la auditoría externa señala findings post-close, sin abrir un Charter nuevo.</li>
</ul>
<p>El Post 9 cubrió la disciplina aplicada manualmente sobre CHARTER-18. Este post cubre lo que vino después: los dos patrones nombrados, el documento canónico que los nombra (<code>CHARTER-CHAIN-EVOLUTION.md</code>), el schema de telemetría que los mide, los dos <em>CLI helpers</em> que los scaffold-ean — y, como cierre del arco editorial entero, una hora y diecisiete minutos más tarde, un meta-patrón filosófico que reabsorbe ambos hacia arriba.</p>
<p>Es el último post del arco. El blog que el Post 1 abrió por delante cierra aquí por atrás.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="2-pattern-1--pre-declare-refresh">2. Pattern 1 — Pre-declare refresh<a href="https://straymark.dev/es/blog/pattern-1-and-pattern-2-chain-evolution#2-pattern-1--pre-declare-refresh" class="hash-link" aria-label="Enlace directo al 2. Pattern 1 — Pre-declare refresh" title="Enlace directo al 2. Pattern 1 — Pre-declare refresh" translate="no">​</a></h2>
<p>La definición literal, copiada del documento canónico:</p>
<blockquote>
<p><em>"A dedicated refresh PR lands between Charter-N close and Charter-(N+1) declare. It touches only the non-locked sections of the SpecKit artifacts (plan.md, data-model.md, contracts, quickstart.md, research.md)."</em></p>
</blockquote>
<p>Esto es exactamente lo que Sentinel hizo manualmente para CHARTER-18 en el Post 9. La diferencia entre Post 9 y Post 10 es de tipo: el Post 9 documenta el procedimiento; el Post 10 documenta su <em>activación condicionada</em> — cuándo el framework recomienda al adoptante que aplique Pattern 1.</p>
<p>Los criterios de activación son cuantificables, y el documento los nombra sin atenuar:</p>
<ul>
<li class="">El módulo tiene <strong>≥ 3 Charters cerrados</strong> sobre la misma spec.</li>
<li class="">La media móvil (últimos 3 Charters) del campo <code>agent_quality.r_n_plus_one_emergent_count</code> en la telemetría es <strong>mayor a 6</strong>.</li>
<li class="">No ha aterrizado un <em>refresh PR</em> desde el último <em>branch point</em>.</li>
</ul>
<p>El umbral <code>&gt; 6</code> no es arbitrario. Es Sentinel CHARTER-18 convertido en regla: el promedio de hallazgos emergentes (riesgos descubiertos durante el Charter que no estaban declarados en el plan original) durante CHARTER-15, 16, 17 fue exactamente lo que disparó la sensación de que la spec estaba acumulando demasiada deuda. El framework, en lugar de pedirle al adoptante que confíe en su intuición, le da un número que su telemetría puede comparar.</p>
<p>Lo que produce Pattern 1, cuando se aplica:</p>
<ul>
<li class="">Una tabla categorizada en <code>research.md</code> que enumera lo descubierto en los Charters anteriores en cuatro tipos: <em>reusable patterns</em>, <em>code gaps</em>, <em>discipline patterns</em>, <em>empirical corrections</em>.</li>
<li class="">Decisiones operacionales explícitas (<code>D1</code>, <code>D2</code>, etc.) si la categorización evidencia trade-offs.</li>
<li class="">Citas en el <code>§Context</code> del siguiente Charter, por <code>id</code>, hacia los items integrados.</li>
<li class="">Un bloque de telemetría <code>pre_declare_refresh:</code> opt-in en el <code>charter-telemetry.yaml</code> del Charter que recibe el refresh.</li>
</ul>
<p>La métrica que sostiene el patrón viene de Sentinel CHARTER-18 mismo, citada literal en <code>CHARTER-CHAIN-EVOLUTION.md</code>:</p>
<blockquote>
<p><em>"Sentinel CHARTER-18 was the first Charter in a 7-Charter chain to close cleanly without a mid-flight remediation Charter. <code>estimation_drift_factor: 1.0</code>, <code>pre_work.items_discovered_during_planning: 0</code>, <code>overall_satisfaction: 5/5</code>."</em></p>
</blockquote>
<p>Un solo dominio. <code>N=1</code>. El documento lo dice sin atajos: el patrón está validado empíricamente <em>en Sentinel</em>. Esperar al segundo dominio antes de cristalizarlo más alto.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="3-pattern-2--amend-on-emergence">3. Pattern 2 — Amend-on-emergence<a href="https://straymark.dev/es/blog/pattern-1-and-pattern-2-chain-evolution#3-pattern-2--amend-on-emergence" class="hash-link" aria-label="Enlace directo al 3. Pattern 2 — Amend-on-emergence" title="Enlace directo al 3. Pattern 2 — Amend-on-emergence" translate="no">​</a></h2>
<p>La definición literal:</p>
<blockquote>
<p><em>"The amendment rides the same execute branch as the original Charter (the branch is still mergeable to main; the amendment commit lands on top)."</em></p>
</blockquote>
<p>La idea: cuando un Charter ya cerrado recibe findings de auditoría externa post-close — <em>critical</em> o <em>high</em> — el framework no obliga a abrir un Charter nuevo. El operador puede <em>amendar</em> el Charter cerrado mientras la rama <code>execute</code> sigue mergeable a <code>main</code>.</p>
<p>La justificación, también literal del documento:</p>
<blockquote>
<p><em>"A new Charter would have created multi-week governance overhead for ~6h of focused engineering."</em></p>
</blockquote>
<p>Esa asimetría — semanas de gobernanza vs. seis horas de ingeniería — es lo que el patrón resuelve. Abrir un Charter nuevo para arreglar cinco findings post-close significa: declarar contexto nuevo, repetir auditoría externa, generar AILOG nuevo, registrar telemetría desde cero. Para una corrección que en código toma una tarde. Pattern 2 dice: no.</p>
<p>Los criterios de activación, también cuantificables:</p>
<ul>
<li class=""><em>Findings</em> Critical/High aparecen post-close, después de la auditoría externa.</li>
<li class="">El criterio de cierre del Charter resultó materialmente incumplido por esos findings.</li>
<li class="">La superficie del fix es menor a 25 archivos.</li>
<li class="">No requiere reapertura arquitectónica (decisiones de diseño que el Charter original asumió como cerradas).</li>
</ul>
<p>Si los cuatro criterios se cumplen, Pattern 2 aplica. Si alguno falla, hay que abrir Charter nuevo.</p>
<p>Lo que produce, cuando se aplica:</p>
<ul>
<li class="">Un commit de <em>amendment</em> sobre la misma rama <code>execute</code> del Charter original.</li>
<li class="">Un AILOG nuevo (no editar el original) con <code>risk_level: high</code>, <code>review_required: true</code>, y un campo <code>amends:</code> que apunta al AILOG original.</li>
<li class="">Una sección <code>## Historical correction (YYYY-MM-DD)</code> en el AILOG original que apunta <em>forward</em> al nuevo. Es archivística: el AILOG original no se reescribe; se enlaza.</li>
<li class="">Un bloque de telemetría <code>post_close_amendment:</code> en el <code>charter-telemetry.yaml</code>.</li>
</ul>
<p>La métrica empírica que sostiene Pattern 2, citada literal:</p>
<blockquote>
<p><em>"Sentinel CHARTER-18 closed 2026-05-15 with audit reports landing 2026-05-15..05-17. Five findings (4 from gpt-5.3-codex, 1 from gemini-2.5-pro) were code-level fixes — DI wiring, retry header parsing, multi-tenant filter, timeout default. The Batch 7.4 amendment closed all five in one cohesive commit (19 files, +2257/-106 lines)."</em></p>
</blockquote>
<p>Un commit, 19 archivos, dos modelos auditores convergiendo en hallazgos similares, cinco fixes. Si hubiera sido Charter nuevo: dos semanas mínimo entre declare, audit externa, y close. En cambio: un <em>amendment</em> en la misma rama, seis horas.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="4-composición-no-exclusión">4. Composición, no exclusión<a href="https://straymark.dev/es/blog/pattern-1-and-pattern-2-chain-evolution#4-composici%C3%B3n-no-exclusi%C3%B3n" class="hash-link" aria-label="Enlace directo al 4. Composición, no exclusión" title="Enlace directo al 4. Composición, no exclusión" translate="no">​</a></h2>
<p>La pieza más interesante del documento — y, creo, la que cierra mejor el arco — es la sección sobre cómo se relacionan los dos patrones. Cita literal:</p>
<blockquote>
<p><em>"A Charter that received Pattern 1 is more likely to avoid Pattern 2, because the refresh absorbs pre-execution risk that would otherwise surface as post-close findings. But CHARTER-18 needed both — the refresh handled spec-level drift; the amendment handled runtime-level drift the refresh did not reach into."</em></p>
</blockquote>
<p>No son patrones rivales. Son aplicaciones del mismo principio en momentos distintos del ciclo. Pattern 1 absorbe deriva <em>de spec</em> — lo que el plan original ya no describe correctamente. Pattern 2 absorbe deriva <em>de runtime</em> — lo que solo se ve cuando el código corre, los auditores externos lo miran fresco, y emerge desde el código mismo.</p>
<p>Sentinel CHARTER-18 necesitó los dos. La spec refrescada eliminó los hallazgos emergentes que un audit cycle posterior habría tenido que remediar atomicamente; la <em>amendment</em> posterior absorbió lo que el refresh no podía haber predicho — wiring de DI, parsing de headers de retry, un filtro multi-tenant, un default de timeout. Cosas que el plan no podía conocer y que solo emergieron cuando el código existió.</p>
<p>El framework, al nombrar los dos patrones y declarar su composición explícita, hace algo que me importa subrayar: deja constancia de que la disciplina no es lineal. No hay un solo punto de inspección antes de cada Charter; hay un punto antes (Pattern 1) y un punto después (Pattern 2), y ambos pueden ser necesarios en el mismo Charter. La cadena evoluciona; los patrones también.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="5-el-schema-y-los-helpers">5. El schema y los helpers<a href="https://straymark.dev/es/blog/pattern-1-and-pattern-2-chain-evolution#5-el-schema-y-los-helpers" class="hash-link" aria-label="Enlace directo al 5. El schema y los helpers" title="Enlace directo al 5. El schema y los helpers" translate="no">​</a></h2>
<p>Lo que <code>fw-4.16.0</code> añadió al schema de telemetría son dos sub-objetos opcionales en <code>charter-telemetry.schema.v0.json</code> v0.2:</p>
<div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token key atrule" style="color:#00a4db">pre_declare_refresh</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">enabled</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> boolean</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">refresh_pr</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> string </span><span class="token punctuation" style="color:#393A34">|</span><span class="token plain"> null</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">refresh_aidec</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> string </span><span class="token punctuation" style="color:#393A34">|</span><span class="token plain"> null</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">reusable_patterns_integrated</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> integer  </span><span class="token comment" style="color:#999988;font-style:italic"># ≥ 0</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">code_gaps_integrated</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> integer</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">discipline_patterns_integrated</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> integer</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">empirical_corrections_integrated</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> integer</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">operator_decisions_ratified</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> integer</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">post_close_amendment</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">applied</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> boolean</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">trigger</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> external_audit </span><span class="token punctuation" style="color:#393A34">|</span><span class="token plain"> production_incident </span><span class="token punctuation" style="color:#393A34">|</span><span class="token plain"> deferred_implementation</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">ailog_id</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> string</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">findings_closed</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> integer</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">files_modified</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> integer</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">effort_hours</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> number</span><br></div></code></pre></div></div>
<p>Contadores enteros, no narrativas. La decisión es deliberada: lo que el telemetry schema captura es lo que el agente o el operador pueden contar mecánicamente. Lo que no se puede contar — <em>qué tan profundo era el problema, qué tan astuto fue el fix</em> — vive en el AILOG, no en la telemetría. El schema mide la <em>forma</em> del trabajo; los documentos llevan el <em>contenido</em>.</p>
<p>Y <code>cli-3.14.0</code> añadió dos helpers, ninguno mutador:</p>
<ul>
<li class="">
<p><strong><code>straymark charter refresh-suggest &lt;module&gt; [--threshold N]</code></strong> — <em>read-only</em>. Lee la telemetría de los últimos tres Charters cerrados del módulo, computa la media móvil de <code>r_n_plus_one_emergent_count</code>, y emite una recomendación: <em>refresh-now</em>, <em>not-needed</em>, o <em>insufficient-data</em>. <em>Exit 0</em> siempre. Es informacional, nunca CI gate.</p>
</li>
<li class="">
<p><strong><code>straymark charter amend &lt;CHARTER-ID&gt; --trigger &lt;kind&gt; --ailog-title &lt;title&gt; [--findings-closed N] [--merge-into &lt;PATH&gt;]</code></strong> — scaffolding. Crea un AILOG stub con los campos correctos (<code>risk_level: high</code>, <code>review_required: true</code>, <code>amends:</code> apuntando al original), añade la sección <code>## Historical correction</code> al AILOG original, y renderiza el bloque YAML de <code>post_close_amendment:</code>. <strong>No toca git.</strong></p>
</li>
</ul>
<p>La elección de mantener los dos helpers humildes — uno solo recomienda, el otro solo prepara — es coherente con la decisión A1 del Post 4: <em>"el CLI orquesta pero no invoca APIs"</em>. Aquí: el CLI sugiere pero no decide; scaffold-ea pero no muta. El humano sigue siendo el punto donde la disciplina ocurre. El framework solo le pone las herramientas a la mano.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="6-setenta-y-siete-minutos-después">6. Setenta y siete minutos después<a href="https://straymark.dev/es/blog/pattern-1-and-pattern-2-chain-evolution#6-setenta-y-siete-minutos-despu%C3%A9s" class="hash-link" aria-label="Enlace directo al 6. Setenta y siete minutos después" title="Enlace directo al 6. Setenta y siete minutos después" translate="no">​</a></h2>
<p>Hay una pieza más que vale la pena registrar antes del cierre del arco. PR #157 se fusionó a las 00:31 UTC del 16 de mayo. PR #160 — el del Post 1, <code>EMERGENT-OBSERVATION-DESIGN.md</code>, fw-4.17.0 — se fusionó a las 01:48 UTC del mismo día. Setenta y siete minutos después.</p>
<p>Lo que pasó en esos setenta y siete minutos es el cierre invertido del arco. El meta-patrón filosófico que el Post 1 nombró — <em>observación emergente compuesta de vínculos formales más permiso cultural para señalar</em> — se cristalizó <strong>una hora y diecisiete minutos</strong> después de los dos meta-patrones operativos de este post. El meta-patrón filosófico no precede a la disciplina; la sucede. Es la lectura ascendente de la misma evidencia.</p>
<p><code>CHARTER-CHAIN-EVOLUTION.md</code> lo registra explícitamente en su sección <code>§Related</code>:</p>
<blockquote>
<p><em>"EMERGENT-OBSERVATION-DESIGN.md — the meta-pattern of which Pattern 1 and Pattern 2 are applications (formal cross-referencing + cultural permission to surface)."</em></p>
</blockquote>
<p>Pattern 1 es composición de vínculos formales (la telemetría <code>r_n_plus_one_emergent_count</code>, las citas por <code>id</code> en el <code>§Context</code>, los AILOGs categorizados) con permiso cultural (la regla de que un agente debe señalar deriva entre spec y código cuando la encuentra). Pattern 2 es composición similar (los AILOGs con <code>amends:</code>, la sección <code>Historical correction</code> enlazando <em>forward</em>) con permiso para señalar findings post-close en lugar de absorberlos en silencio. Los dos patrones son aplicaciones del mismo principio cultural+estructural que el Post 1 nombró por encima.</p>
<p>Es un final que me sigue gustando: el blog que abrió diciendo <em>"el agente vio algo que nadie le pidió ver"</em> cierra diciendo, en el episodio anterior por orden cronológico, <em>"aquí están las dos cosas que el agente puede ver bien porque el framework las nombra"</em>.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="7-cierre-del-arco">7. Cierre del arco<a href="https://straymark.dev/es/blog/pattern-1-and-pattern-2-chain-evolution#7-cierre-del-arco" class="hash-link" aria-label="Enlace directo al 7. Cierre del arco" title="Enlace directo al 7. Cierre del arco" translate="no">​</a></h2>
<p>Diez posts. Once episodios cubiertos (<code>H-01</code> a <code>H-13</code>, con varios agrupados). Una decisión editorial — la publicación retroactiva — que el Post 2 introdujo y que los nueve posts siguientes ejercieron sin violar. Un compromiso bilingüe que se mantuvo en cada cierre.</p>
<p>Algunas cosas que aprendí escribiendo el blog y que vale la pena registrar antes de cerrarlo:</p>
<ol>
<li class="">
<p><strong>El patrón nace de la disciplina.</strong> La frase ya apareció en el Post 9, pero el arco completo la sostiene. Los meta-patrones de este post no se diseñaron; se extrajeron. Cada hito documentado tuvo primero su episodio operativo y después su nombre.</p>
</li>
<li class="">
<p><strong>La cadencia no es uniforme.</strong> Diecinueve días entre el primer commit (Post 2, 27 enero) y la primera unidad acotada con auditoría externa (Post 3, 25 abril). Cinco horas entre disciplina aplicada y disciplina canonizada (Post 9, 14 mayo). Setenta y siete minutos entre dos meta-patrones y su lectura filosófica (Posts 10 y 1, 16 mayo). El proyecto pasó por todas las velocidades, y el blog las registra todas.</p>
</li>
<li class="">
<p><strong>El framework no es neutro respecto a su adopter.</strong> Sentinel hizo posible que cada patrón se validara empíricamente antes de cristalizarse. El blog no esconde esa procedencia; la subraya como precondición metodológica.</p>
</li>
<li class="">
<p><strong>Lo que no se nombra, no se ve.</strong> El Post 5 lo formuló como <em>visibilidad estructural</em>; el Post 7 lo aplicó a la deuda transversal; el Post 8 lo señaló sobre el outlier de idioma. Es la regularidad más persistente del arco. Existir como artefacto técnico no basta. El nombre activa el artefacto.</p>
</li>
</ol>
<p>El arco que el blog vino a contar — los hitos <code>H-01</code> a <code>H-13</code>, los cuatro nombres del proyecto, los seis Planes, los Charters first-class, el audit cycle externo, el Issue #113, el rebrand a StrayMark, el TDE, el outlier del audit-prompt, la disciplina manual, y los dos meta-patrones — cierra aquí. Lo que queda en deuda explícita: <code>H-14</code>, la TUI <code>straymark explore</code> (que apareció lateralmente en el Post 8 como herramienta de visibilidad), y los hitos candidatos <code>H-?-A</code> a <code>H-?-E</code> que <code>PLAN-INVESTIGACION.md §1.43-55</code> listó como pendientes de decisión. Posible segunda tanda futura. Sin promesa.</p>
<p>Una última observación, simétrica al Post 1. Aquel post abrió diciendo: <em>"el agente vio algo que nadie le pidió ver"</em>. Lo que el blog cierra registrando, después de diez episodios, es la otra mitad de la frase: el agente vio porque el framework lo había puesto en condiciones de ver. La observación emergente del Post 1 es la prueba; los patrones nombrados de este post son las precondiciones. Cada cosa que el agente señaló durante los cuatro meses que cubre el arco fue posible porque algún episodio anterior había puesto un artefacto, un disparador, un vínculo formal, una superficie visible donde antes no había nada.</p>
<p>El blog termina de contar la historia. El framework sigue.</p>
<hr>
<p><em>Anclas: <a href="https://github.com/StrangeDaysTech/straymark/issues/156" target="_blank" rel="noopener noreferrer" class="">Issue #156</a>. PR <a href="https://github.com/StrangeDaysTech/straymark/pull/157" target="_blank" rel="noopener noreferrer" class="">#157</a> — <code>fw-4.16.0 / cli-3.14.0</code> (fusionado 2026-05-16 00:31 UTC). Documento canónico: <a href="https://github.com/StrangeDaysTech/straymark/blob/main/dist/.straymark/00-governance/CHARTER-CHAIN-EVOLUTION.md" target="_blank" rel="noopener noreferrer" class=""><code>CHARTER-CHAIN-EVOLUTION.md</code></a>. Schema: <code>dist/.straymark/schemas/charter-telemetry.schema.v0.json</code> v0.2. Meta-patrón sucesor: <a href="https://github.com/StrangeDaysTech/straymark/blob/main/dist/.straymark/00-governance/EMERGENT-OBSERVATION-DESIGN.md" target="_blank" rel="noopener noreferrer" class=""><code>EMERGENT-OBSERVATION-DESIGN.md</code></a>, <code>fw-4.17.0</code> (fusionado 2026-05-16 01:48 UTC, 77 minutos después).</em></p>
<p><em>Este documento fue elaborado con asistencia de herramientas de IA generativa (Claude 4.7); toda la responsabilidad del contenido recae en el autor humano.</em></p>
<p><em>— Fin del arco H-01 → H-13 del blog StrayMark.</em></p>]]></content:encoded>
            <category>straymark</category>
            <category>charters</category>
            <category>chain-evolution</category>
            <category>governance</category>
        </item>
        <item>
            <title><![CDATA[AGENTS.md como estándar universal]]></title>
            <link>https://straymark.dev/es/blog/agents-md-as-a-universal-standard</link>
            <guid>https://straymark.dev/es/blog/agents-md-as-a-universal-standard</guid>
            <pubDate>Fri, 15 May 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[Cuatro meses entre la intuición y el estándar abierto]]></description>
            <content:encoded><![CDATA[<p><em>Cuatro meses entre el primer AIDEC del proyecto — "los agentes de IA son una única audiencia técnica" — y el estándar abierto que lo operacionalizó. <code>AGENTS.md</code> en la raíz del repo, leído por quince CLIs de distintos vendors, reemplazando la proliferación de CLAUDE.md / GEMINI.md / .cursorrules y una docena más.</em></p>
<!-- -->
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="1-cuatro-meses-entre-la-intuición-y-el-estándar">1. Cuatro meses entre la intuición y el estándar<a href="https://straymark.dev/es/blog/agents-md-as-a-universal-standard#1-cuatro-meses-entre-la-intuici%C3%B3n-y-el-est%C3%A1ndar" class="hash-link" aria-label="Enlace directo al 1. Cuatro meses entre la intuición y el estándar" title="Enlace directo al 1. Cuatro meses entre la intuición y el estándar" translate="no">​</a></h2>
<p>El 15 de mayo de 2026, a las 19:05 UTC, el PR <a href="https://github.com/StrangeDaysTech/straymark/pull/155" target="_blank" rel="noopener noreferrer" class="">#155</a> cerró el framework como <code>fw-4.15.0 / cli-3.13.2</code>. Lo que trajo es un solo archivo nuevo en la lista de directivas que el CLI inyecta: <code>AGENTS.md</code>, en la raíz del repo del adoptante, paralelo a los que ya estaban (<code>CLAUDE.md</code>, <code>GEMINI.md</code>, <code>.github/copilot-instructions.md</code>, <code>.cursorrules</code>, <code>.cursor/rules/straymark.md</code>).</p>
<p>Esto sería trivial si no fuera porque hace exactamente cuatro meses, el 27 de enero de 2026, el primer AIDEC del proyecto — el que el Post 2 cubrió con la anécdota del año tipográfico — había declarado:</p>
<blockquote>
<p><em>"AI agents (Claude, Gemini, Copilot, Cursor) process instructions equally well in any language, so translating their config files provides no functional benefit."</em></p>
</blockquote>
<p>Esa frase, escrita seis horas después del <em>initial commit</em> del proyecto, contenía una intuición que el framework venía operativizando desde entonces: los agentes son un solo público técnico. Mantenían los archivos de configuración en inglés (mientras la documentación humana se traducía a tres idiomas) porque la audiencia "agentes IA" no se beneficiaba de la traducción. Lo que faltaba para cerrar esa intuición era darle un solo lugar al que apuntar, sin tener que clonar el archivo cuatro o cinco veces para cada vendor distinto.</p>
<p>Este post cubre exactamente eso: cómo <code>AGENTS.md</code> — un estándar abierto donado a la Agentic AI Foundation en diciembre de 2025 — completó cuatro meses después la decisión que el primer AIDEC había abierto en enero.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="2-la-fragmentación-que-agentsmd-resuelve">2. La fragmentación que <code>AGENTS.md</code> resuelve<a href="https://straymark.dev/es/blog/agents-md-as-a-universal-standard#2-la-fragmentaci%C3%B3n-que-agentsmd-resuelve" class="hash-link" aria-label="Enlace directo al 2-la-fragmentación-que-agentsmd-resuelve" title="Enlace directo al 2-la-fragmentación-que-agentsmd-resuelve" translate="no">​</a></h2>
<p>Entre 2024 y 2026, mientras los CLIs de agentes IA proliferaban, cada uno inventó su propio formato de archivo de instrucciones:</p>
<ul>
<li class="">Anthropic publicó <code>CLAUDE.md</code> con la primera versión de Claude Code.</li>
<li class="">Google adoptó <code>GEMINI.md</code> para Gemini CLI.</li>
<li class="">GitHub estableció <code>.github/copilot-instructions.md</code> para Copilot CLI.</li>
<li class="">Cursor empezó con <code>.cursorrules</code> y migró luego a <code>.cursor/rules/*.md</code>.</li>
<li class="">OpenAI usó otro path para Codex CLI; Aider, Devin, Continue, Roo Code, Factory Droids, Sourcegraph Amp, Zed AI, Windsurf, Amazon Q tenían cada uno el suyo.</li>
</ul>
<p>Un adoptante de StrayMark que usara dos o tres de esos CLIs tenía que mantener dos o tres copias del mismo contenido, sincronizadas a mano, esperando que ninguna divergiera. El framework hasta <code>fw-4.14.x</code> reconocía esa fragmentación en su comando <code>straymark init</code>: inyectaba en los cinco archivos vendor-específicos más comunes. Pero los otros diez o quince CLIs quedaban fuera. El adoptante los manejaba copiando contenido a mano.</p>
<p>A finales de 2025, la comunidad de proyectos open-source que producía CLIs de agentes hizo lo que se hace cuando una fragmentación se vuelve costosa: acordaron un estándar. <code>AGENTS.md</code> en la raíz del repo, leído por todos. La donación a la Agentic AI Foundation (Linux Foundation, diciembre 2025) le dio gobernanza institucional. La especificación es deliberadamente mínima: un archivo Markdown, sin schema impuesto, en una ubicación predecible. Lo que cada CLI hace con ese archivo es asunto suyo; la pregunta canónica — <em>"¿dónde está la configuración de agentes para este repo?"</em> — tiene ahora una sola respuesta.</p>
<p>Para mayo de 2026, la lista de CLIs que leen <code>AGENTS.md</code> incluye (cita literal del cuerpo del PR #155):</p>
<blockquote>
<p><em>"Claude Code, OpenAI Codex CLI, Cursor, Aider, Devin, Sourcegraph Amp, Google Jules, Zed AI, Continue, Roo Code, Factory Droids, GitHub Copilot, Gemini CLI, Windsurf, Amazon Q and others."</em></p>
</blockquote>
<p>Quince CLIs. Algunos siguen leyendo <em>también</em> sus archivos vendor-específicos por compatibilidad histórica. Pero los quince saben buscar <code>AGENTS.md</code> primero.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="3-adoptar-sin-matar-lo-propio">3. Adoptar sin matar lo propio<a href="https://straymark.dev/es/blog/agents-md-as-a-universal-standard#3-adoptar-sin-matar-lo-propio" class="hash-link" aria-label="Enlace directo al 3. Adoptar sin matar lo propio" title="Enlace directo al 3. Adoptar sin matar lo propio" translate="no">​</a></h2>
<p>La decisión más interesante de <code>fw-4.15.0</code> no es adoptar <code>AGENTS.md</code>; eso era inevitable una vez que el estándar tenía masa crítica. Lo interesante es <em>cómo</em>. El cuerpo del PR lo articula sin atenuar:</p>
<blockquote>
<p><em>"Parallel to CLAUDE.md / GEMINI.md: marker block points to STRAYMARK.md, with a minimum-viable body below for readers that cannot follow relative links."</em></p>
</blockquote>
<p>Tres palabras clave: <strong>parallel</strong>, <strong>marker block</strong>, <strong>minimum-viable body</strong>.</p>
<p><em>Parallel</em> significa que <code>AGENTS.md</code> no reemplaza los archivos vendor-específicos. Coexiste. El framework sigue inyectando <code>CLAUDE.md</code>, <code>GEMINI.md</code>, <code>.cursorrules</code> y los demás. La razón es pragmática: algunos CLIs (notablemente Cursor en su versión legacy) requieren que el contenido completo esté embebido, no detrás de un link relativo. Mantener los archivos hermanos preserva esa compatibilidad sin que cada adoptante tenga que pelear con su CLI específico.</p>
<p><em>Marker block</em> es la convención que el framework ya usaba en los demás archivos vendor-específicos: un bloque HTML-commented entre <code>&lt;!-- straymark:begin --&gt;</code> y <code>&lt;!-- straymark:end --&gt;</code> que apunta a <code>STRAYMARK.md</code> como source-of-truth. Cualquier <code>straymark update-framework</code> reemplaza solo lo que está entre esos marcadores. Lo que el adoptante haya escrito <em>afuera</em> de ellos — por ejemplo, instrucciones propias del proyecto — se preserva intacto. El framework respeta el archivo del adoptante; solo gobierna su propia sección.</p>
<p><em>Minimum-viable body</em> es la concesión a los CLIs que no siguen relative links. Debajo del bloque de marcadores, <code>AGENTS.md</code> tiene un cuerpo corto con lo esencial: identidad del agente, requisitos de revisión, checklist pre-commit, snippet de frontmatter regulatorio, categorías de riesgo NIST AI 600-1, reglas de observabilidad, convención de nombrado. Es suficiente para que un agente que no pueda leer <code>STRAYMARK.md</code> opere correctamente; es insuficiente para reemplazar al documento canónico. La asimetría es deliberada: queremos que el agente <em>quiera</em> abrir <code>STRAYMARK.md</code>.</p>
<p>El detalle defensivo del CLI (<code>cli/src/commands/remove.rs:13</code>) cierra el flanco operativo: <code>AGENTS.md</code> se agregó a <code>LEGACY_DIRECTIVE_TARGETS</code>. Si un adoptante pierde su <code>.straymark/dist-manifest.yml</code> y ejecuta <code>straymark remove</code>, el fallback legacy limpia también <code>AGENTS.md</code> en lugar de dejarlo huérfano. Es housekeeping aburrido, pero es la diferencia entre un framework que se desinstala completamente y uno que deja basura.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="4-sin-adr">4. Sin ADR<a href="https://straymark.dev/es/blog/agents-md-as-a-universal-standard#4-sin-adr" class="hash-link" aria-label="Enlace directo al 4. Sin ADR" title="Enlace directo al 4. Sin ADR" translate="no">​</a></h2>
<p>Vale la pena nombrar una ausencia. La decisión de adoptar <code>AGENTS.md</code> no tuvo ADR propio.</p>
<p>Es un contraste deliberado con el rebrand a StrayMark del Post 6, que sí tuvo <code>ADR-2026-05-08-001</code> público con tres alternativas evaluadas y consecuencias enumeradas. Es también contraste con Phase 2 del Post 12, que tuvo una entrada de CHANGELOG densa con justificación arquitectónica. <code>fw-4.15.0</code> tuvo solo el cuerpo del PR como justificación documental — un cuerpo bueno, con argumento claro, pero no un ADR.</p>
<p>¿Por qué? La respuesta operativa: la decisión se percibió como <strong>agregativa</strong>, no estructural. Adoptar un estándar abierto que coexiste con los formatos existentes no cambia el modelo del framework; solo lo extiende. No hay alternativa cuyo descarte requiera justificación formal: no adoptar <code>AGENTS.md</code> significaría dejar fuera a 15 CLIs por preferencia estética, y nadie tenía ese argumento que hacer.</p>
<p>Pero hay una lección registrable aquí. El blog ha visto el patrón antes — Phase 2 cierra un loop empírico, el rebrand cambia identidad, los meta-patrones del Post 10 nombran lo que ya estaba — y en cada caso la pregunta <em>"¿esto amerita ADR?"</em> tiene una respuesta distinta. La regla operativa que el framework parece haber adoptado, sin nombrarla, es esta: <strong>un ADR se justifica cuando la decisión cierra alternativas costosas y deja registro de las que no se eligieron</strong>. <code>fw-4.15.0</code> no cerró alternativas costosas — solo agregó una capa. Por eso bastó con el PR.</p>
<p>Lo dejo registrado aquí porque vale la pena reconocer que no todo cambio merece ADR, ni todo PR es un documento histórico. La disciplina archivística tiene sus propios criterios.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="5-visibilidad-para-agentes-dos-capas">5. Visibilidad para agentes, dos capas<a href="https://straymark.dev/es/blog/agents-md-as-a-universal-standard#5-visibilidad-para-agentes-dos-capas" class="hash-link" aria-label="Enlace directo al 5. Visibilidad para agentes, dos capas" title="Enlace directo al 5. Visibilidad para agentes, dos capas" translate="no">​</a></h2>
<p>Diez días antes de <code>fw-4.15.0</code>, el 9 de mayo, se cerró el Issue <a href="https://github.com/StrangeDaysTech/straymark/issues/113" target="_blank" rel="noopener noreferrer" class="">#113</a> — el episodio que el Post 5 documentó como <em>"Charters invisibles para los agentes"</em>. El operador había trabajado seis horas con un agente capaz, atento, con el aparato canónico de onboarding cargado, y el agente nunca había propuesto usar un Charter. La conclusión que aquel post canonizó: la <em>visibilidad estructural</em> es responsabilidad del framework, no propiedad del agente.</p>
<p><code>fw-4.15.0</code> cubre la otra cara del mismo problema.</p>
<p>El Post 5 trataba de <strong>visibilidad estructural interna</strong>: cómo aseguramos que un agente que ya está leyendo nuestro repo descubra los conceptos centrales del framework. La respuesta del PR #122 (Post 5) fue multiplicar las superficies internas donde Charter aparece como concepto: <code>STRAYMARK.md §15</code>, directivas <code>CLAUDE.md</code>/<code>GEMINI.md</code>, skills <code>/straymark-*</code>, output de <code>status</code>, templates, puente con SpecKit. Nueve superficies internas.</p>
<p>Este post trata de <strong>visibilidad estructural externa</strong>: cómo aseguramos que cualquier agente que entra al repo, sin importar su vendor, encuentre el aparato del framework. La respuesta de <code>fw-4.15.0</code> es adoptar el punto de encuentro canónico que la comunidad eligió. Una superficie externa, leída por quince vendors.</p>
<p>Las dos capas tienen el mismo eje conceptual — <em>un artefacto técnico solo existe para el agente si la superficie lo nombra</em> — pero distinto alcance. Visibilidad interna garantiza que el agente vea los Charters cuando está leyendo <code>STRAYMARK.md</code>. Visibilidad externa garantiza que el agente vea <code>STRAYMARK.md</code> cuando entra al repo. Una capa sin la otra es incompleta.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="6-lo-que-el-adoptante-hace-al-ejecutar-update-framework">6. Lo que el adoptante hace al ejecutar <code>update-framework</code><a href="https://straymark.dev/es/blog/agents-md-as-a-universal-standard#6-lo-que-el-adoptante-hace-al-ejecutar-update-framework" class="hash-link" aria-label="Enlace directo al 6-lo-que-el-adoptante-hace-al-ejecutar-update-framework" title="Enlace directo al 6-lo-que-el-adoptante-hace-al-ejecutar-update-framework" translate="no">​</a></h2>
<p>La parte operativa del release, citada literal del CHANGELOG:</p>
<blockquote>
<p><em>"straymark update-framework brings the new template and injects AGENTS.md at the project root. The injection follows the same rules as every other directive target: it creates the file if absent, replaces the marker block on subsequent runs, and appends safely when the file pre-exists without StrayMark markers (very common in 2026 — many adopters already hand-maintain an AGENTS.md)."</em></p>
</blockquote>
<p>Tres comportamientos importantes:</p>
<ol>
<li class=""><strong>Si no existe</strong>, el CLI lo crea con el template canónico.</li>
<li class=""><strong>Si ya existe y tiene marcadores StrayMark</strong>, el CLI reemplaza solo el contenido entre marcadores.</li>
<li class=""><strong>Si ya existe sin marcadores</strong> — caso muy común en 2026, porque muchos adoptantes ya escribían su propio <code>AGENTS.md</code> a mano — el CLI <strong>agrega sus marcadores al final del archivo</strong>, sin tocar lo que el adoptante había escrito.</li>
</ol>
<p>Es el mismo respeto archivístico que el blog ya documentó en Posts 3 y 6: el framework gobierna <em>su sección</em>, no el archivo entero. Si el adoptante quiere escribir instrucciones propias del proyecto en su <code>AGENTS.md</code> — políticas internas, convenciones de naming, instrucciones específicas para una codebase particular — esas instrucciones quedan intactas en cada <code>update</code>. El bloque de StrayMark vive en su pequeña frontera marcada, y se actualiza dentro de esa frontera.</p>
<p>La nota del CHANGELOG cierra con una pequeña advertencia operativa que vale la pena registrar: <em>"If your .gitignore excludes AGENTS.md, adjust it before update-framework so the injection lands in version control."</em> Es honesta sobre los edge cases que el framework no puede resolver por su cuenta — la elección del adoptante de ignorar el archivo es soberanía, no error.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="7-cierre">7. Cierre<a href="https://straymark.dev/es/blog/agents-md-as-a-universal-standard#7-cierre" class="hash-link" aria-label="Enlace directo al 7. Cierre" title="Enlace directo al 7. Cierre" translate="no">​</a></h2>
<p>Lo que aprendí del proceso, en cuatro tesis:</p>
<ol>
<li class="">
<p><strong>Cuatro meses entre intuición y materialización es lo que toma cerrar bien un loop.</strong> El AIDEC de enero contenía la intuición — <em>"los agentes son un solo público"</em>. <code>fw-4.15.0</code> la cerró con un estándar abierto. Entre las dos, el framework iteró sobre arquetipos vendor-específicos hasta que apareció el sustituto universal. La intuición temprana fue correcta; el plazo fue el que la maduración del ecosistema requería.</p>
</li>
<li class="">
<p><strong>Adoptar un estándar abierto no exige renunciar al formato propio.</strong> <code>AGENTS.md</code> coexiste con <code>CLAUDE.md</code>, <code>GEMINI.md</code>, <code>.cursorrules</code>. La decisión no es "uno reemplaza a los demás" sino "uno se suma a los demás cuando aporta". El framework gana visibilidad externa sin perder compatibilidad con CLIs que requieren formatos específicos.</p>
</li>
<li class="">
<p><strong>No todo cambio amerita ADR.</strong> El rebrand a StrayMark cerró alternativas costosas y dejó registro formal de las descartadas. <code>fw-4.15.0</code> solo agregó una capa universal: ningún ADR habría enriquecido la decisión. La disciplina archivística tiene criterios operativos, no doctrinas.</p>
</li>
<li class="">
<p><strong>Visibilidad para agentes opera en dos capas.</strong> La capa interna (Post 5, <code>fw-4.12.0</code>) asegura que el agente vea los conceptos del framework cuando está leyendo el repo. La capa externa (<code>fw-4.15.0</code>) asegura que el agente entre al repo por la puerta correcta sin importar qué CLI lo orqueste. Una sin la otra deja agentes capaces leyendo en silencio o agentes desorientados sin punto de entrada.</p>
</li>
</ol>
<hr>
<p><em>Anclas: PR <a href="https://github.com/StrangeDaysTech/straymark/pull/155" target="_blank" rel="noopener noreferrer" class="">#155</a> — <code>fw-4.15.0 / cli-3.13.2</code> (fusionado 2026-05-15 19:05 UTC). AIDEC original (Post 2): <code>.chronicle/07-ai-audit/decisions/AIDEC-2025-01-27-001-i18n-strategy.md</code> (commit <code>7b7193e</code>, ID con año tipográfico). Template inyectado: <code>dist/dist-templates/directives/AGENTS.md</code>. Especificación del estándar: <a href="https://agents.md/" target="_blank" rel="noopener noreferrer" class="">agents.md</a> — donado a la Agentic AI Foundation (Linux Foundation), diciembre 2025.</em></p>
<p><em>Este documento fue elaborado con asistencia de herramientas de IA generativa (Claude 4.7); toda la responsabilidad del contenido recae en el autor humano.</em></p>]]></content:encoded>
            <category>straymark</category>
            <category>agents-md</category>
            <category>governance</category>
            <category>estándares-abiertos</category>
            <category>i18n</category>
        </item>
        <item>
            <title><![CDATA[Abrir el framework]]></title>
            <link>https://straymark.dev/es/blog/opening-the-framework</link>
            <guid>https://straymark.dev/es/blog/opening-the-framework</guid>
            <pubDate>Fri, 15 May 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[Setenta y dos horas de gestos que sólo cobran sentido juntos]]></description>
            <content:encoded><![CDATA[<p><em>Dos gestos en setenta y dos horas: cerrar el último 5% de la paridad i18n (20/20/20 docs de gobernanza en EN + ES + zh-CN) y publicar el badge de CLA en el README. Pequeños por separado; juntos, el momento en que el framework deja de hablarse a sí mismo y empieza a hablarle a cualquiera que quiera leerlo.</em></p>
<!-- -->
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="1-dos-gestos-en-setenta-y-dos-horas">1. Dos gestos en setenta y dos horas<a href="https://straymark.dev/es/blog/opening-the-framework#1-dos-gestos-en-setenta-y-dos-horas" class="hash-link" aria-label="Enlace directo al 1. Dos gestos en setenta y dos horas" title="Enlace directo al 1. Dos gestos en setenta y dos horas" translate="no">​</a></h2>
<p>El 13 de mayo de 2026, a las 06:20 UTC, se fusionó <code>fw-4.13.4</code>. Cerró dos huecos pequeños de cobertura i18n — el documento de referencia ISO-25010 que solo estaba en inglés, y el template del Charter que faltaba en chino simplificado. Veintidós archivos canónicos del framework alcanzaron paridad estructural EN/ES/zh-CN.</p>
<p>El 15 de mayo, a las 00:14 UTC, sesenta y cinco horas después, se fusionó el PR <a href="https://github.com/StrangeDaysTech/straymark/pull/154" target="_blank" rel="noopener noreferrer" class="">#154</a>. Agregó un badge al README — el de CLA Assistant, ese cuadrito visible que avisa al visitante que el repo acepta contribuciones bajo un Contributor License Agreement. La política del CLA ya existía desde meses antes en <code>CONTRIBUTING.md</code>; lo único que cambió fue que ahora aparece en el README al primer vistazo.</p>
<p>Este post cubre los dos gestos. Vistos por separado, son pequeños — uno completa el último 5% de un trabajo técnico, el otro publica algo que ya estaba escrito. Vistos juntos, son el momento en que el framework decide presentarse al exterior. La pieza que un proyecto open-source hace cuando deja de hablar solo consigo mismo y empieza a hablar con quien quiera leerlo.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="2-el-último-5-de-la-cobertura-i18n">2. El último 5% de la cobertura i18n<a href="https://straymark.dev/es/blog/opening-the-framework#2-el-%C3%BAltimo-5-de-la-cobertura-i18n" class="hash-link" aria-label="Enlace directo al 2. El último 5% de la cobertura i18n" title="Enlace directo al 2. El último 5% de la cobertura i18n" translate="no">​</a></h2>
<p><code>fw-4.13.4</code> no es un release grande. El PR <a href="https://github.com/StrangeDaysTech/straymark/pull/144" target="_blank" rel="noopener noreferrer" class="">#144</a> tiene 511 líneas de adición y casi todas son traducciones. Pero el resumen del PR dice algo que vale la pena registrar:</p>
<blockquote>
<p><em>"Brings governance docs to full 20/20/20 parity across EN + ES + zh-CN."</em></p>
</blockquote>
<p>Veinte sobre veinte sobre veinte. Veintidós archivos canónicos en <code>dist/.straymark/00-governance/</code> (el conteo creció después; en mayo eran veinte), todos con su contraparte en <code>i18n/es/</code> y <code>i18n/zh-CN/</code>. Paridad completa, no aproximada.</p>
<p>Los dos archivos que cerraron la paridad son específicos:</p>
<ul>
<li class=""><code>ISO-25010-2023-REFERENCE.md</code> — la referencia normativa al estándar internacional de calidad de software, citada desde principios del framework. Hasta <code>fw-4.13.4</code> existía solo en inglés. El release añadió <code>i18n/es/ISO-25010-2023-REFERENCE.md</code> y <code>i18n/zh-CN/ISO-25010-2023-REFERENCE.md</code>, 150 líneas cada uno.</li>
<li class=""><code>charter-template.md</code> en zh-CN. El template del Charter ya estaba traducido al español; faltaba el chino simplificado, 211 líneas.</li>
</ul>
<p>No es un trabajo glamoroso. Es la pieza que cierra un cuadro. Pero importa por dos cosas. La primera: hasta ese release, un adoptante chino que clonara el framework iba a encontrar templates esenciales en inglés solamente, lo cual contradice la promesa de que el framework está disponible en tres idiomas. La segunda: el blog ya documentó en Post 8 que la cobertura i18n del framework era casi completa, con dos gaps menores quedando como deuda anotada. <code>fw-4.13.4</code> cerró esa deuda. Lo que parecía una nota lateral en un post sobre el outlier del audit-prompt resultó ser un release entero, con su propia entrada en CHANGELOG.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="3-lo-que-se-traduce-y-lo-que-no">3. Lo que se traduce y lo que no<a href="https://straymark.dev/es/blog/opening-the-framework#3-lo-que-se-traduce-y-lo-que-no" class="hash-link" aria-label="Enlace directo al 3. Lo que se traduce y lo que no" title="Enlace directo al 3. Lo que se traduce y lo que no" translate="no">​</a></h2>
<p>Hay una regla operativa que el PR #144 codifica explícitamente y que vale la pena dejar registrada, porque es la regla más clara del framework respecto a i18n:</p>
<blockquote>
<p><em>"LLM-processed assets (skills, workflows, schemas) stay EN-only; human-primary artifacts get translated."</em></p>
</blockquote>
<p>Es decir: lo que leen los agentes IA — skills, workflows en <code>.claude/</code>, <code>.gemini/</code>, <code>.agent/</code>, schemas en <code>dist/.straymark/schemas/</code>, prompts en <code>dist/.straymark/audit-prompts/</code> — vive solo en inglés. Lo que leen los humanos — documentación, principios, guías de contribución, templates con copy human-facing — se traduce a los tres idiomas.</p>
<p>Es el mismo principio que el Post 13 documentó como ancestro intelectual del AGENTS.md universal: los agentes son un solo público técnico que no se beneficia de traducción. Lo registrable aquí es que la regla, en mayo, está escrita en un PR como criterio operativo, no como intuición. Las propuestas técnicas la citan; los reviewers la usan para decidir si un archivo nuevo va a <code>i18n/</code> o no.</p>
<p>Un detalle adicional del PR #144 vale la pena registrar literal:</p>
<blockquote>
<p><em>"docs/contributors/TRANSLATION-GUIDE.md gap was left intentional — its target audience already reads English to read the guide."</em></p>
</blockquote>
<p>La guía de traducción quedó intencionalmente en inglés porque su audiencia — los contribuidores que traducen el framework a otros idiomas — necesariamente lee inglés ya. Es honestidad operativa: la paridad 20/20/20 no es 22/22/22 para todos los archivos del repo. Es 20/20/20 para los archivos cuya traducción aporta valor al usuario. La diferencia entre cobertura total y cobertura aplicable.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="4-el-badge-que-no-introdujo-nada-nuevo">4. El badge que no introdujo nada nuevo<a href="https://straymark.dev/es/blog/opening-the-framework#4-el-badge-que-no-introdujo-nada-nuevo" class="hash-link" aria-label="Enlace directo al 4. El badge que no introdujo nada nuevo" title="Enlace directo al 4. El badge que no introdujo nada nuevo" translate="no">​</a></h2>
<p>PR #154 es el opuesto pedagógico de <code>fw-4.13.4</code>. Donde <code>fw-4.13.4</code> cierra un trabajo técnico, PR #154 publica algo que ya estaba ahí. Sus 12 líneas de cambio agregan exactamente esto al README (en inglés, español y chino):</p>
<div class="language-markdown codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-markdown codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token url" style="color:#36acaa">[</span><span class="token url content" style="color:#36acaa">![CLA assistant</span><span class="token url" style="color:#36acaa">](</span><span class="token url" style="color:#36acaa">https://cla-assistant.io/readme/badge/StrangeDaysTech/straymark</span><span class="token url" style="color:#36acaa">)</span><span class="token plain">](https://cla-assistant.io/StrangeDaysTech/straymark)</span><br></div></code></pre></div></div>
<p>Un badge. Una imagen pequeña que aparece arriba del README, junto a los demás badges del proyecto (licencia, versión, downloads). Visualmente nada del otro mundo.</p>
<p>Pero el badge no es decoración. Es señal. Y la señal dice algo concreto: <em>"este repo acepta contribuciones externas, y aquí están las reglas"</em>. Cualquier visitante que abra el README puede hacer clic en el badge y llegar al CLA Assistant — el servicio que automáticamente comenta en el primer pull request de cualquier contribuidor, pidiendo que firme el Contributor License Agreement. Una sola firma cubre todas las futuras contribuciones al proyecto.</p>
<p>Lo importante es que el CLA, el <code>CONTRIBUTING.md</code>, la política completa de revisión, todo eso ya existía antes de PR #154. Estaba codificado, vivo, operativo. El framework ya aceptaba contribuciones externas — solo que el visitante casual del repo tenía que abrir <code>CONTRIBUTING.md</code> para enterarse de cómo funcionaba.</p>
<p>PR #154 hace una distinción que vale la pena nombrar: <strong>tener la política</strong> y <strong>publicar la política</strong> son dos cosas distintas. La primera es disciplina interna; la segunda es invitación pública. Hasta el 15 de mayo, el framework tenía la política. Desde el 15 de mayo, la publica.</p>
<p>Es un cambio editorial, no arquitectónico. Pero el día que un proyecto open-source decide poner el badge de CLA Assistant arriba del README es el día que decide presentarse formalmente como adoptable por terceros. Es el momento en que el framework deja de ser un proyecto-de-uno-y-su-adopter (Sentinel) y se vuelve un proyecto que <em>acepta</em> tener más adopters, más contribuidores, más manos.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="5-cuándo-un-framework-se-siente-listo-para-ser-visto">5. Cuándo un framework se siente listo para ser visto<a href="https://straymark.dev/es/blog/opening-the-framework#5-cu%C3%A1ndo-un-framework-se-siente-listo-para-ser-visto" class="hash-link" aria-label="Enlace directo al 5. Cuándo un framework se siente listo para ser visto" title="Enlace directo al 5. Cuándo un framework se siente listo para ser visto" translate="no">​</a></h2>
<p>Estos dos hitos, leídos juntos, registran un momento específico en la vida de un framework joven: el momento en que se siente listo para ser visto por gente que no lo escribió.</p>
<p><code>fw-4.13.4</code> cierra la promesa técnica. Si el framework dice ser bilingüe español-inglés con soporte experimental para chino simplificado, los veintidós archivos canónicos deben estar en los tres idiomas. No diecinueve sobre veinte. No veinte sobre veintiuno con dos pendientes. Veinte sobre veinte sobre veinte. La paridad completa es lo que vuelve la promesa creíble cuando el visitante revisa.</p>
<p>PR #154 cierra la promesa social. Si el framework dice aceptar contribuciones externas, el badge del CLA en el README es la forma estándar de la industria de decirlo. Sin el badge, la apertura existe pero hay que descubrirla; con el badge, está señalada. El primer click del visitante encuentra el camino.</p>
<p>Vale la pena nombrar la asimetría de los dos gestos. Cerrar el último 5% de un trabajo técnico cuesta exactamente eso — un release dedicado, dos archivos traducidos, una entrada de CHANGELOG. Publicar una política preexistente cuesta doce líneas de Markdown. El cuesta-poco es a veces el gesto operativamente más significativo, porque cambia cómo el mundo exterior percibe el proyecto sin cambiar nada del proyecto en sí.</p>
<p>Es la versión "abrir el framework" del patrón que el Post 5 documentó como <em>visibilidad estructural</em>: lo que existe pero no está nombrado, no existe para el agente. Aquí: lo que existe pero no está publicado, no existe para el adoptante externo. Setenta y dos horas en mayo, dos hitos pequeños — uno técnico, uno editorial — y el framework cruza la línea entre <em>"funciona pero quien lo escribió lo sabe"</em> y <em>"funciona y cualquiera puede verlo"</em>.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="6-cierre-simbólico-del-arco">6. Cierre simbólico del arco<a href="https://straymark.dev/es/blog/opening-the-framework#6-cierre-simb%C3%B3lico-del-arco" class="hash-link" aria-label="Enlace directo al 6. Cierre simbólico del arco" title="Enlace directo al 6. Cierre simbólico del arco" translate="no">​</a></h2>
<p>Con este post, el blog cubre los últimos hitos pendientes de la segunda tanda que <code>RETOMAR-AQUI.md §5</code> listó después del cierre del arco principal H-01 → H-13. Los cuatro candidatos identificados — <code>H-?-C</code> (validate + schemas), <code>H-?-A</code> (AGENTS.md universal), <code>H-?-B</code> (cobertura i18n completa), <code>H-?-E</code> (CLA badge) — están todos cubiertos: tres en posts propios (Posts 12, 13, este) y uno combinado.</p>
<p>Lo que aprendí escribiendo la segunda tanda, mirando los cuatro hitos juntos:</p>
<ul>
<li class=""><strong>Phase 2 / validate</strong> (Post 12) es estructural: el framework empieza a verificar lo que prometía.</li>
<li class=""><strong>TUI explore</strong> (Post 11) es de visibilidad: el framework se vuelve navegable.</li>
<li class=""><strong>AGENTS.md universal</strong> (Post 13) es de alcance: el framework se vuelve descubrible por cualquier CLI.</li>
<li class=""><strong>Cobertura i18n completa + CLA badge</strong> (este post) es de apertura: el framework se vuelve visible al visitante externo.</li>
</ul>
<p>Cada uno cubre una dimensión distinta de la misma idea, que el blog ya dejó codificada en posts anteriores: lo que un framework dice que es no basta para que sea; tiene que estar presente en cada superficie donde alguien — agente, adopter externo, visitante — pueda construir un modelo del proyecto. Los hitos de la segunda tanda son la versión madura de la <em>visibilidad estructural</em> que el Post 5 nombró con un Issue de gobernanza.</p>
<p>Ahora sí, después de Post 14, no hay candidatos más en la cola. Si emergen nuevos hitos del framework entre hoy y cuando la próxima sesión del blog se active, RETOMAR-AQUI volverá a usarse como punto de retomo. Si no emergen, este post es el cierre real — el cierre con el que el blog completa el inventario que se propuso cubrir.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="7-cierre">7. Cierre<a href="https://straymark.dev/es/blog/opening-the-framework#7-cierre" class="hash-link" aria-label="Enlace directo al 7. Cierre" title="Enlace directo al 7. Cierre" translate="no">​</a></h2>
<p>Lo que aprendí del proceso, en cuatro tesis:</p>
<ol>
<li class="">
<p><strong>Cobertura total cuesta poco al final del trabajo y mucho al principio.</strong> El último 5% — esos dos archivos en chino — son release dedicado. Pero solo son trivialmente cerrables porque el otro 95% ya estaba hecho. La paridad 20/20/20 no nace al principio; se persigue durante meses y se cierra al final con un PR pequeño.</p>
</li>
<li class="">
<p><strong>Tener una política y publicarla son dos cosas distintas.</strong> El CLA del framework existía meses antes que el badge. Doce líneas de Markdown convirtieron una política interna en una invitación pública. El día que pones el badge no inventas nada; declaras que estás listo para que te encuentren.</p>
</li>
<li class="">
<p><strong>La regla operativa de qué se traduce es archivística.</strong> Lo que leen humanos se traduce; lo que leen agentes vive en inglés. Esa distinción, intuida desde el primer AIDEC de enero, se vuelve criterio explícito de revisión en mayo. Cada archivo nuevo del framework pasa por esa pregunta antes de elegir destino.</p>
</li>
<li class="">
<p><strong>Cuándo un framework se vuelve adoptable por terceros es decisión, no estado.</strong> Hay un día en el que el operador decide que el framework ya puede ser visto sin pena por gente que no lo escribió. Ese día se materializa en gestos pequeños — completar traducciones, publicar el badge — que no cambian la funcionalidad pero cambian la postura. El framework deja de hablar consigo mismo.</p>
</li>
</ol>
<p>Con esto el blog cierra la segunda tanda. El arco que arrancó retroactivamente con la prehistoria del proyecto (Post 2, enero) y se completó con los meta-patrones (Post 10, mayo) tiene ahora también su corolario: los hitos que volvieron al framework adoptable. Catorce posts, veintiocho archivos (catorce ES + catorce EN), entre veinticinco y veintiséis mil palabras por idioma. Como decía el cierre del Post 10: <em>el blog termina de contar la historia. El framework sigue</em>.</p>
<hr>
<p><em>Anclas: PR <a href="https://github.com/StrangeDaysTech/straymark/pull/144" target="_blank" rel="noopener noreferrer" class="">#144</a> — <code>fw-4.13.4</code> (fusionado 2026-05-13 06:20 UTC, cobertura i18n completa). PR <a href="https://github.com/StrangeDaysTech/straymark/pull/154" target="_blank" rel="noopener noreferrer" class="">#154</a> — badge CLA Assistant en READMEs (fusionado 2026-05-15 00:14 UTC). Política completa: <code>CONTRIBUTING.md</code> (raíz del repo + traducciones en <code>docs/i18n/{es,zh-CN}/CONTRIBUTING.md</code>).</em></p>
<p><em>Este documento fue elaborado con asistencia de herramientas de IA generativa (Claude 4.7); toda la responsabilidad del contenido recae en el autor humano.</em></p>
<p><em>— Fin de la segunda tanda del blog StrayMark.</em></p>]]></content:encoded>
            <category>straymark</category>
            <category>i18n</category>
            <category>cla</category>
            <category>governance</category>
            <category>apertura</category>
        </item>
        <item>
            <title><![CDATA[La disciplina manual antes del patrón]]></title>
            <link>https://straymark.dev/es/blog/manual-discipline-before-the-pattern</link>
            <guid>https://straymark.dev/es/blog/manual-discipline-before-the-pattern</guid>
            <pubDate>Thu, 14 May 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[Doce aprendizajes en un Issue, tres gates en un PR, y un Charter que cerró limpio antes de que existiera el nombre]]></description>
            <content:encoded><![CDATA[<p><em>Siete Charters consecutivos sobre un plan de un mes en Sentinel, ejecutando CHARTER-18 a mano con la sensación de que cualquier paso en falso enterraría seis Charters de trabajo. Cinco horas para canonizar la disciplina manual como gobernanza upstream — sin nombrar todavía el patrón.</em></p>
<!-- -->
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="1-la-pregunta-correcta">1. La pregunta correcta<a href="https://straymark.dev/es/blog/manual-discipline-before-the-pattern#1-la-pregunta-correcta" class="hash-link" aria-label="Enlace directo al 1. La pregunta correcta" title="Enlace directo al 1. La pregunta correcta" translate="no">​</a></h2>
<p>El <a href="https://github.com/StrangeDaysTech/straymark/issues/150" target="_blank" rel="noopener noreferrer" class="">Issue #150</a>, abierto el 14 de mayo a las 16:59 UTC, no buscaba un <em>yes/no</em>. Lo que el operador estaba pidiendo era reformular la pregunta:</p>
<blockquote>
<p><em>"The real question the bridge doc should address is how, not whether: what discipline ensures spec stays in sync with code during multi-Charter execution without the regeneration step lying about the parts that already shipped."</em></p>
</blockquote>
<p>La disciplina ya existía. Se estaba aplicando en Sentinel en ese momento, sobre <code>CHARTER-18</code>, manualmente, con la sensación de que cualquier paso en falso enterraba el trabajo de seis Charters anteriores. Lo que faltaba — y lo que el Issue documentaba con precisión incómoda — era el nombre. El cuándo. Las reglas que un adoptante futuro pudiera seguir sin haber pasado por el dolor de inventarlas.</p>
<p>Este post cubre las cinco horas que separan ese Issue del PR que canonizó la disciplina como gobernanza upstream, los 12 aprendizajes empíricos que justificaron la canonización, y el episodio operativo concreto — <code>CHARTER-18</code> de Sentinel — que ejerció el patrón antes de que el patrón existiera. El siguiente post cubrirá lo que vino 27 horas después: el nombre.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="2-siete-charters-sobre-un-mismo-plan">2. Siete Charters sobre un mismo plan<a href="https://straymark.dev/es/blog/manual-discipline-before-the-pattern#2-siete-charters-sobre-un-mismo-plan" class="hash-link" aria-label="Enlace directo al 2. Siete Charters sobre un mismo plan" title="Enlace directo al 2. Siete Charters sobre un mismo plan" translate="no">​</a></h2>
<p>El contexto, en una sola línea: Sentinel ejecutó <code>specs/002-commshub/plan.md</code> — escrito en el commit <code>be29421</code> el 21 de abril de 2026 — a través de <strong>siete Charters consecutivos</strong> (<code>CHARTER-07</code> a <code>CHARTER-17</code>), un mes calendario, sin refrescar el plan ni una vez.</p>
<p>El plan original era bueno. Estaba escrito con cuidado, con las cuatro user stories (US1-US4) detalladas, con el data-model declarado, con los contracts esbozados. Pero el plan era una fotografía de cómo el operador imaginaba en abril que el código se iba a comportar. La ejecución descubrió cosas que el plan no podía haber anticipado:</p>
<ul>
<li class="">Patrones de infraestructura que aparecieron <em>durante</em> la ejecución y resultaron reutilizables (un namespace en <code>core.processed_events</code>, un <code>withRLS</code> helper, triggers PL/pgSQL para invariantes).</li>
<li class="">Gaps de código que el plan asumió resueltos (<code>AnomalyDetector</code> <em>half-built</em>, idempotency dedup faltante, <code>Recipient.TenantID</code> schema gap).</li>
<li class="">Patrones de Charter/audit que se cristalizaron a lo largo del mes (cross-family audit cycle, HTTP layer test coverage gap, cursor pagination con strict-greater-than).</li>
</ul>
<p>Cuando llegó el momento de planear <code>CHARTER-18</code> para US5, el plan tenía un mes de antigüedad y el código tenía un mes de aprendizaje empírico encima. Las dos cosas no estaban sincronizadas. Y <code>SPECKIT-CHARTER-BRIDGE.md</code> — el documento del framework que normalmente respondería <em>"¿qué hago aquí?"</em> — guardaba silencio sobre el caso. La regla <em>"cómo se mantiene la spec sincronizada con el código durante ejecución multi-Charter"</em> no existía todavía.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="3-los-doce-aprendizajes-empíricos">3. Los doce aprendizajes empíricos<a href="https://straymark.dev/es/blog/manual-discipline-before-the-pattern#3-los-doce-aprendizajes-emp%C3%ADricos" class="hash-link" aria-label="Enlace directo al 3. Los doce aprendizajes empíricos" title="Enlace directo al 3. Los doce aprendizajes empíricos" translate="no">​</a></h2>
<p>El Issue #150 enumera los doce aprendizajes que se habían acumulado sin reflejar en el plan. La tabla literal, agrupada por tipo, vale la pena dejarla a la vista:</p>






































































<table><thead><tr><th>#</th><th>Tipo</th><th>Aprendizaje</th></tr></thead><tbody><tr><td>1</td><td>Patrón de infra</td><td><code>core.processed_events</code> con namespace <code>module='commshub'</code> reutilizable — el plan describe su propia tabla.</td></tr><tr><td>2</td><td>Patrón de infra</td><td><code>EnvSecretLoader</code> + Secret Manager projection (PRs #70/71) — el plan describe acceso directo.</td></tr><tr><td>3</td><td>Patrón de infra</td><td><code>withRLS</code> helper como single-source-of-truth para aislamiento por tenant — el plan no lo ancla.</td></tr><tr><td>4</td><td>Patrón de infra</td><td>FR-005 triggers PL/pgSQL como enforcement de invariantes — el plan describe checks a nivel app.</td></tr><tr><td>5</td><td>Gap de código</td><td><code>AnomalyDetector</code> <em>half-built</em> — el plan implica funcional.</td></tr><tr><td>6</td><td>Gap de código</td><td>Idempotency dedup en <code>delivery_log</code> faltante — el plan implica coordinado.</td></tr><tr><td>7</td><td>Gap de código</td><td><code>Recipient.TenantID</code> schema gap — el plan referencia <code>tenant_id</code> como si existiera.</td></tr><tr><td>8</td><td>Gap de código</td><td>Per-tier rate limit overrides ausentes — el plan dice <em>"3-tier hierarchy"</em> sin mencionar que US1 implementó un tier uniforme.</td></tr><tr><td>9</td><td>Patrón de Charter</td><td>Cross-family external audit cycle obligatorio (6 consecutivos) — el plan silencioso.</td></tr><tr><td>10</td><td>Patrón de Charter</td><td>HTTP layer test coverage gap — el plan silencioso en test layering.</td></tr><tr><td>11</td><td>Patrón de Charter</td><td>Cursor pagination tuple con strict-greater-than — el plan silencioso.</td></tr><tr><td>12</td><td>Patrón de Charter</td><td>Dispatcher interface-stable swap pattern — el plan silencioso.</td></tr></tbody></table>
<p>Cuatro patrones de infraestructura descubiertos o refinados durante la ejecución. Cuatro gaps de código que el plan no anticipó. Cuatro patrones de Charter/audit cristalizados sobre la marcha. Doce piezas, en un solo mes, todas reales. El plan no las tenía. Y el siguiente Charter — <code>CHARTER-18</code> — iba a leer el plan como si no existieran.</p>
<p>La estimación que el operador documentó en el Issue es honesta:</p>
<blockquote>
<p><em>"Estimated probability of ≥1 critical/high finding from stale-premise inheritance: ~50%."</em></p>
</blockquote>
<p>Cara o cruz, en una palabra. La mitad de los Charters arrancados sobre plan rancio terminan con un finding crítico que un audit cycle posterior debe remediar atomicamente pre-close. Y la otra mitad solo se libra por suerte.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="4-alternative-4-la-disciplina-aplicada-a-mano">4. Alternative 4: la disciplina aplicada a mano<a href="https://straymark.dev/es/blog/manual-discipline-before-the-pattern#4-alternative-4-la-disciplina-aplicada-a-mano" class="hash-link" aria-label="Enlace directo al 4. Alternative 4: la disciplina aplicada a mano" title="Enlace directo al 4. Alternative 4: la disciplina aplicada a mano" translate="no">​</a></h2>
<p>Lo que pasó dentro de Sentinel, ese mismo día, antes de que la disciplina tuviera nombre: el operador evaluó cinco alternativas concretas y eligió la cuarta. El AIDEC privado de Sentinel — <code>AIDEC-2026-05-14-001-speckit-plan-scope-limited-us5-refresh.md</code> — registra el análisis sin atenuar. Lo parafraseo aquí porque el contenido detallado vive en el repo privado, pero la estructura del razonamiento es lo que importa:</p>
<ul>
<li class=""><strong>Alternative 1 — <em>"Léelo como antes"</em>.</strong> Mantener el plan desactualizado y leerlo como las seis veces anteriores. Costo: pagar la deuda en audit cycle posterior, ~50% probabilidad de finding crítico.</li>
<li class=""><strong>Alternative 2 — Regenerar todo con <code>/speckit-plan</code>.</strong> Riesgo: sobreescribir aserciones sobre US1-US4 que el código real <em>no</em> cumple; el regenerador no sabe del estado actual.</li>
<li class=""><strong>Alternative 3 — Refresh en otro PR sin restricciones.</strong> Mismo riesgo que Alt 2 más fricción de revisión.</li>
<li class=""><strong>Alternative 4 — Scope-limited refresh + 3 gates.</strong> La elegida.</li>
<li class=""><strong>Alternative 5 — Diferir CHARTER-18, hacer un Charter de refactor first.</strong> Costo de calendario alto, beneficio marginal sobre Alt 4.</li>
</ul>
<p>La cuarta consistió en tres mecanismos concretos:</p>
<p><strong>Primer mecanismo — <em>scope-limited prompt</em>.</strong> Ejecutar <code>/speckit-plan</code> con un <em>prompt</em> explícitamente restrictivo: regenera solo la Phase 7+8 correspondiente a US5; deja US1-US4 byte por byte como están, marcadas con comentarios <code>&lt;!-- LOCKED: prior US shipped --&gt;</code> que el agente debe respetar. Sin esa restricción explícita, la regeneración de SpecKit es destructiva: rescribe todo el plan, sobreescribiendo descripciones que el código real ya contradice.</p>
<p><strong>Segundo mecanismo — <em>Gate (a): validación contra realidad de código</em>.</strong> Un script ad-hoc, ~30 líneas de bash + grep, que difea cada entidad non-US5 de <code>data-model.md</code> contra el schema real en <code>db/migrations/*.sql</code>, y cada endpoint non-US5 de <code>contracts/*.md</code> contra los handler signatures reales en <code>internal/modules/commshub/handler_*.go</code>. Cualquier divergencia bloquea merge. El script existe en el repo de Sentinel; no es elegante, es operativo. Lo que el framework canonizará después como gate (a) ya estaba ahí, como bash artesanal.</p>
<p><strong>Tercer mecanismo — <em>Gate (b): revisión granular hunk-por-hunk</em>.</strong> Revisar <code>git diff</code> archivo por archivo, hunk por hunk, sin aceptar cambios a secciones <em>locked</em> sin justificación. El operador anota explícitamente la fricción esperada en R1 del AIDEC: si el agente regenera más hunks que los necesarios, el revisor humano se cansa y la disciplina colapsa. Mitigación: hunks de más de 50 líneas disparan revisión P1.</p>
<p><strong>Cuarto mecanismo — <em>Gate (c): two-PR split</em>.</strong> El refresh es un PR independiente, revisado contra <strong>código actual</strong>. El Charter-fill que sigue, otro PR, revisado contra el plan ya refrescado. No mezclar las dos revisiones — porque si se mezclan, la deuda del refresh se esconde detrás del trabajo nuevo.</p>
<p>Cuatro mecanismos. Aplicados manualmente, sin documentación upstream que los avalara. Un solo adoptante (yo), una sola sesión, y la sensación todo el tiempo de estar resolviendo un caso que nadie había resuelto antes.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="5-el-resultado">5. El resultado<a href="https://straymark.dev/es/blog/manual-discipline-before-the-pattern#5-el-resultado" class="hash-link" aria-label="Enlace directo al 5. El resultado" title="Enlace directo al 5. El resultado" translate="no">​</a></h2>
<p><code>CHARTER-18</code> cerró el mismo día. Las métricas del Charter Telemetry, registradas literal en el YAML del cierre:</p>
<ul>
<li class=""><code>estimation_drift_factor: 1.0</code> — el Charter terminó exactamente en el rango de horas estimado.</li>
<li class=""><code>pre_work.items_discovered_during_planning: 0</code> — ningún ítem inesperado apareció durante la fase de planning.</li>
<li class=""><code>overall_satisfaction: 5/5</code> — la mejor calibración subjetiva del operador en toda la cadena.</li>
</ul>
<p>Más importante que las métricas: <code>CHARTER-18</code> fue el <strong>primer Charter de la cadena de siete que cerró sin un Charter de remediación mid-flight</strong>. Los seis anteriores habían necesitado, cada uno, al menos una remediación atómica pre-close para cubrir divergencias entre lo declarado y lo entregado. CHARTER-18 no. El statement del operador en el cierre, citado literal del <code>CHARTER-CHAIN-EVOLUTION.md</code> posterior:</p>
<blockquote>
<p><em>"The SpecKit refresh from PR #76 eliminated most ambiguity that drove drift in prior Charters. No mid-flight remediation Charter required — the EC1..EC15 empirical-corrections inventory in research.md absorbed what would have been pre-execution risk into in-execution awareness."</em></p>
</blockquote>
<p>La disciplina manual funcionó. No solo cerró el Charter limpio; cambió la naturaleza del riesgo. Lo que antes era riesgo pre-ejecución (descubrir divergencias durante la ejecución del Charter, remediar atomicamente) se volvió consciencia pre-planning (el inventario <code>EC1..EC15</code> enumera las correcciones empíricas antes de declarar el Charter). El riesgo no se elimina; se mueve a un momento donde es manejable.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="6-cuatro-horas-y-cuarenta-minutos">6. Cuatro horas y cuarenta minutos<a href="https://straymark.dev/es/blog/manual-discipline-before-the-pattern#6-cuatro-horas-y-cuarenta-minutos" class="hash-link" aria-label="Enlace directo al 6. Cuatro horas y cuarenta minutos" title="Enlace directo al 6. Cuatro horas y cuarenta minutos" translate="no">​</a></h2>
<p>La cronología vale la pena dejarla precisa, porque es lo que el blog viene a registrar:</p>
<ul>
<li class=""><strong>14 may, 16:59 UTC</strong> — Issue #150 abierto. Los doce aprendizajes enumerados, los tres gates propuestos, el análisis de probabilidad publicado.</li>
<li class=""><strong>14 may, 21:39 UTC</strong> — PR <a href="https://github.com/StrangeDaysTech/straymark/pull/152" target="_blank" rel="noopener noreferrer" class="">#152</a> fusionado. <code>fw-4.14.3</code> shipped. <em>"Spec maintenance during multi-Charter execution"</em> añadido como sección nueva a <code>SPECKIT-CHARTER-BRIDGE.md</code> con los tres gates canonizados literalmente como gobernanza del framework. <strong>Cuatro horas y cuarenta minutos</strong> entre la pregunta y la respuesta upstream.</li>
</ul>
<p>Lo que el PR #152 documentó como gobernanza es exactamente lo que el AIDEC privado había aplicado a mano horas antes. Las tres gates con los mismos nombres: validation against code reality (gate a), granular hunk-by-hunk review (gate b), two-PR split (gate c). Más cuatro heurísticas de <em>cuándo refrescar</em>: ≥3 Charters cerrados sobre el mismo plan, ≥4 semanas + ≥2 Charters, conteo de <code>R&lt;N&gt;(new)</code> &gt; 6, target US toca infra refinada. Más una nota explícita sobre por qué NO volver a correr <code>/speckit-tasks</code> (porque destruye los marcadores <code>[X]</code> y las anotaciones <code>*CHARTER-NN:* &lt;sha&gt;</code> que forman el rastro histórico). Más una nota de roadmap mencionando un futuro <code>straymark spec-drift</code> CLI que mecanizaría gate (a).</p>
<p>Cuatro horas. No es exagerado decir que el framework escribió la guía mientras el operador todavía tenía el <code>git diff</code> abierto en otra ventana. La disciplina y su canonización fueron prácticamente simultáneas. Y eso me importa registrarlo porque es el orden inverso al que el aparato académico de governance suele asumir: primero la teoría, después la práctica. Aquí fue al revés. Primero la práctica, mientras dolía. Después la teoría, mientras el dolor todavía estaba fresco.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="7-cierre">7. Cierre<a href="https://straymark.dev/es/blog/manual-discipline-before-the-pattern#7-cierre" class="hash-link" aria-label="Enlace directo al 7. Cierre" title="Enlace directo al 7. Cierre" translate="no">​</a></h2>
<p>Lo que aprendí del proceso, en cuatro tesis:</p>
<ol>
<li class="">
<p><strong>El patrón nace de la disciplina, no al revés.</strong> Los tres gates de <code>fw-4.14.3</code> no se diseñaron en abstracto; se <em>extrajeron</em> de un episodio operativo concreto, horas después de aplicarse manualmente. La gobernanza es post-empírica cuando el framework respeta el orden.</p>
</li>
<li class="">
<p><strong>La probabilidad explícita es disciplina.</strong> <em>"~50% probabilidad de finding crítico por herencia de premisa rancia"</em> no es exactitud bayesiana; es una afirmación pública que obliga a justificar la decisión. Sin esa cifra, la pregunta <em>"¿refrescamos?"</em> se decide por intuición. Con esa cifra, se decide por aritmética de riesgo.</p>
</li>
<li class="">
<p><strong>Doce aprendizajes en treinta días es la cadencia real.</strong> No es ruido capturable con <em>"déjame leerlo después"</em>. Es densidad empírica que el plan original no podía haber anticipado, y que destruye cualquier asunción de planning de largo plazo. La cadencia del desarrollo con agentes es esto.</p>
</li>
<li class="">
<p><strong>Cuatro horas no es récord; es propiedad del proceso.</strong> Cuando la disciplina ya está aplicada en un dominio, canonizarla upstream es ejecución, no diseño. Lo mismo que vimos en el Post 4 sobre el audit cycle externo (<em>"cinco PRs en un día"</em>), lo mismo en el Post 6 sobre el rebrand (<em>"cuarenta y tres minutos"</em>). El framework no inventó la disciplina; la extrajo y le puso nombre.</p>
</li>
</ol>
<p>Sigue, en el siguiente post, el último episodio del arco que el blog vino a contar: <em>"Pattern 1 + Pattern 2 — chain evolution"</em> (<code>H-12</code>). Veintisiete horas después del PR #152, los tres gates de gobernanza se cristalizaron como dos meta-patrones nombrados — <em>pre-declare refresh</em> y <em>amend-on-emergence</em> — con telemetry schema y CLI helpers. Es el cierre del arco que el Post 1 abrió por delante.</p>
<hr>
<p><em>Anclas: <a href="https://github.com/StrangeDaysTech/straymark/issues/150" target="_blank" rel="noopener noreferrer" class="">Issue #150</a> (14 may 16:59 UTC). PR <a href="https://github.com/StrangeDaysTech/straymark/pull/152" target="_blank" rel="noopener noreferrer" class="">#152</a> — <code>fw-4.14.3</code> (14 may 21:39 UTC). Sección canonizada: <code>SPECKIT-CHARTER-BRIDGE.md §"Spec maintenance during multi-Charter execution"</code>. Métricas del CHARTER-18 reportadas en <code>CHARTER-CHAIN-EVOLUTION.md</code> (fw-4.16.0). Fuente privada parafraseada conforme <code>GUIA-EDITORIAL.md §7</code>: <code>AIDEC-2026-05-14-001-speckit-plan-scope-limited-us5-refresh.md</code> en el repo de Sentinel.</em></p>
<p><em>Este documento fue elaborado con asistencia de herramientas de IA generativa (Claude 4.7); toda la responsabilidad del contenido recae en el autor humano.</em></p>]]></content:encoded>
            <category>straymark</category>
            <category>charters</category>
            <category>speckit</category>
            <category>disciplina</category>
            <category>governance</category>
        </item>
        <item>
            <title><![CDATA[El audit-prompt era el outlier]]></title>
            <link>https://straymark.dev/es/blog/the-audit-prompt-was-the-outlier</link>
            <guid>https://straymark.dev/es/blog/the-audit-prompt-was-the-outlier</guid>
            <pubDate>Wed, 13 May 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[El único archivo del framework que vivía en otro idioma]]></description>
            <content:encoded><![CDATA[<p><em>Un archivo entre decenas vivía al revés — canónico en español en un framework canónico en inglés, durante seis semanas, sin que nadie lo notara. Un fix de mantenimiento que registra algo con lo que el blog se encuentra una y otra vez: los outliers enseñan la convención por contraste.</em></p>
<!-- -->
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="1-una-sola-línea-del-commit">1. Una sola línea del commit<a href="https://straymark.dev/es/blog/the-audit-prompt-was-the-outlier#1-una-sola-l%C3%ADnea-del-commit" class="hash-link" aria-label="Enlace directo al 1. Una sola línea del commit" title="Enlace directo al 1. Una sola línea del commit" translate="no">​</a></h2>
<p>Esta es la entrada operativa del post 8. El commit <code>a8a1ac5</code> del 12 de mayo de 2026 carga un cuerpo que se abre con esta frase:</p>
<blockquote>
<p><em>"The unified audit-prompt template at <code>dist/.straymark/audit-prompts/</code> was the only framework artifact whose canonical content lived in Spanish — every other template, skill, workflow, and governance doc follows the EN-canonical + <code>i18n/&lt;lang&gt;/</code> overlay pattern resolved by <code>cli/src/utils.rs:146</code>."</em></p>
</blockquote>
<p>Un solo archivo. Entre docenas. Vivía al revés. Y vivía así desde mayo del año anterior, sin que nadie lo notara.</p>
<p>Este post es corto a propósito. La corrección que cubre — PR <a href="https://github.com/StrangeDaysTech/straymark/pull/142" target="_blank" rel="noopener noreferrer" class="">#142</a>, <code>fw-4.13.3</code> y <code>cli-3.12.3</code>, fusionado el 13 de mayo — no es un hito narrativo grande. Es una pieza de mantenimiento. Pero registra una de las regularidades que más me sigo encontrando en este oficio: los outliers son útiles. Te enseñan la convención por contraste.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="2-de-dónde-venía-el-outlier">2. De dónde venía el outlier<a href="https://straymark.dev/es/blog/the-audit-prompt-was-the-outlier#2-de-d%C3%B3nde-ven%C3%ADa-el-outlier" class="hash-link" aria-label="Enlace directo al 2. De dónde venía el outlier" title="Enlace directo al 2. De dónde venía el outlier" translate="no">​</a></h2>
<p>El audit-prompt no nació en el framework. Nació como una <em>skill</em> local de Sentinel — <code>sentinel/.claude/skills/plan-audit/</code> — durante el experimento de los seis Planes que cubrió el Post 3, en abril. Era una skill <em>context-specific</em>, escrita por el operador (yo) en español por razones que ahora se pueden enumerar honestamente: era un experimento privado, el operador habla español, y nadie iba a leer la skill nunca más. La improvisé en mi idioma porque era para mí.</p>
<p>Cuando el experimento se cristalizó en el framework — el arco de fw-4.4.0 a fw-4.9.0 que cubrió el Post 4 — la skill se portó al canonical path <code>dist/.straymark/audit-prompts/audit-prompt.md</code>. El porte fue mecánico: copiar el archivo, generalizarlo lo suficiente para que no mencionara componentes específicos de Sentinel, ajustar la nomenclatura <em>Plan</em> → <em>Charter</em>. Lo que no se hizo: traducirlo al inglés. El archivo entró al framework <em>en el idioma en que lo había escrito</em>. Sin que nadie lo decidiera, el español pasó a ser la versión canónica de ese único artefacto.</p>
<p>El resto del framework — todos los demás templates, todas las skills, los governance docs canónicos — habían sido escritos en inglés desde enero, con español y zh-CN como overlays bajo <code>i18n/&lt;lang&gt;/</code>. El audit-prompt fue la excepción silenciosa, durante seis semanas, hasta el 12 de mayo.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="3-cómo-se-descubrió-por-inspección-visual">3. Cómo se descubrió: por inspección visual<a href="https://straymark.dev/es/blog/the-audit-prompt-was-the-outlier#3-c%C3%B3mo-se-descubri%C3%B3-por-inspecci%C3%B3n-visual" class="hash-link" aria-label="Enlace directo al 3. Cómo se descubrió: por inspección visual" title="Enlace directo al 3. Cómo se descubrió: por inspección visual" translate="no">​</a></h2>
<p>No fue observación emergente del agente. Lo notó el operador, visualmente. La entrada del CHANGELOG lo registra sin metáfora:</p>
<blockquote>
<p><em>"Surfaced empirically when Sentinel audited the <code>straymark explore</code> rendering and the user noted that audit-cycle templates were ES while all other templates and skills were EN."</em></p>
</blockquote>
<p><code>straymark explore</code> es la TUI del framework — el navegador interactivo de documentación que el Post 14 cubrirá. Su valor es renderizar todos los templates lado a lado, en la misma vista. Y cuando todos los templates están lado a lado, uno en otro idioma se nota. Esa es la observación.</p>
<p>Vale la pena dejar el dato porque importa para la honestidad del blog. El Post 1 articuló el patrón de <em>observación emergente</em> — un agente señalando algo que nadie le pidió señalar — y el Post 5 documentó qué pasa cuando ese patrón falta por <em>visibilidad estructural</em>. Este episodio no es ninguno de los dos. Es una observación más pedestre: una superficie nueva del framework (la TUI) puso todos los archivos en visión simultánea, y la inconsistencia se hizo evidente como cuando uno ordena los libros del librero y nota que uno tiene el lomo al revés. Las herramientas también producen visibilidad.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="4-el-fix-tres-movimientos-en-un-commit">4. El fix: tres movimientos en un commit<a href="https://straymark.dev/es/blog/the-audit-prompt-was-the-outlier#4-el-fix-tres-movimientos-en-un-commit" class="hash-link" aria-label="Enlace directo al 4. El fix: tres movimientos en un commit" title="Enlace directo al 4. El fix: tres movimientos en un commit" translate="no">​</a></h2>
<p>PR #142 hizo tres cosas en el mismo commit:</p>
<ul>
<li class=""><strong><code>dist/.straymark/audit-prompts/audit-prompt.md</code></strong> reescrito en inglés como versión canónica. 312 líneas. La traducción cuidó preservar la estructura de severidad y los ejemplos de calibración del original.</li>
<li class=""><strong><code>dist/.straymark/audit-prompts/i18n/es/audit-prompt.md</code></strong> creado como overlay. 318 líneas. Es el contenido español que antes vivía en root, ahora en su lugar correcto.</li>
<li class=""><strong><code>cli/src/commands/charter/audit.rs</code></strong> cableado al resolver i18n. Hasta entonces, el subcomando hardcodeaba el path <code>dist/.straymark/audit-prompts/audit-prompt.md</code> sin consultar el <code>language</code> field del <code>.straymark/config.yml</code> del adopter. Después del PR, lee la configuración del proyecto y resuelve la ruta localizada — si el adopter tiene <code>language: es</code>, recibe el overlay español; si tiene <code>language: zh-CN</code>, hace fallback al EN canonical (no hay traducción zh-CN del audit-prompt todavía); si tiene <code>language: en</code> o no especifica, recibe el canonical.</li>
</ul>
<p>Tres tests nuevos cubren los tres caminos. Cero cambio funcional para usuarios en inglés (que es la mayoría). Para usuarios en español, mejora: antes recibían el prompt en español por accidente (porque el path canónico apuntaba al ES); ahora lo reciben en español por convención (porque el resolver lo decide).</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="5-el-movimiento-lateral">5. El movimiento lateral<a href="https://straymark.dev/es/blog/the-audit-prompt-was-the-outlier#5-el-movimiento-lateral" class="hash-link" aria-label="Enlace directo al 5. El movimiento lateral" title="Enlace directo al 5. El movimiento lateral" translate="no">​</a></h2>
<p>Al hacer el switch de idioma, el operador aprovechó para extraer una especificidad que había quedado del origen Sentinel. La sección §Step 5 del prompt — sobre calibración de severidad de hallazgos — citaba un caso literal del experimento de abril: <em>"Etapa 12 Pub/Sub stub vs gochannel"</em>. Un ejemplo perfectamente didáctico, pero específico de un componente de Sentinel que ningún otro adopter conocería.</p>
<p>La traducción al inglés reemplazó ese ejemplo por una formulación vendor-neutra: <em>"declared deferral, not a defect — a charter that introduces a thin adapter slated for replacement in a future Charter"</em>. La idea — un <em>stub</em> que es deuda declarada, no defecto — se preserva. Lo que se va es el nombre del componente.</p>
<p>El movimiento es pequeño pero coherente con el principio del blog. Cuando hay oportunidad de desligar el framework de un adoptante específico sin perder pedagogía, vale la pena tomarla. Es la misma operación de generalización que Post 3 documentó para los seis Planes y Post 4 para el primer Charter: el contenido empírico se preserva <em>en</em> Sentinel; lo que entra al framework es la abstracción vendor-neutra. El audit-prompt, casi un año después, finalmente terminó de cumplir esa regla.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="6-cierre">6. Cierre<a href="https://straymark.dev/es/blog/the-audit-prompt-was-the-outlier#6-cierre" class="hash-link" aria-label="Enlace directo al 6. Cierre" title="Enlace directo al 6. Cierre" translate="no">​</a></h2>
<p>Tres tesis cortas:</p>
<ol>
<li class="">
<p><strong>En un framework con convención, un solo archivo que la viola es señal de legado, no de diseño.</strong> El audit-prompt era el outlier porque nació antes, y nadie lo migró cuando los demás artefactos se alinearon. Los outliers acumulan procedencia.</p>
</li>
<li class="">
<p><strong>Las herramientas nuevas producen visibilidad.</strong> El switch ES → EN no se decidió por revisión sistemática del repo. Se decidió porque una TUI nueva puso todos los templates en la misma pantalla y la inconsistencia se hizo evidente. Lo mismo aplica a <code>grep</code>, a vistas agregadas, a outputs de <code>status</code>: cada superficie nueva expone qué estaba desalineado.</p>
</li>
<li class="">
<p><strong>Los rebrands chicos son oportunidad de desidentificación.</strong> Cuando tocas un archivo para cambiar idioma, costo marginal cero para también extraer la especificidad de adopter que quedó del origen. El blog ha registrado este patrón antes (Plan → Charter, DevTrail → StrayMark); este es la versión miniatura. El framework se vuelve más vendor-neutro un archivo a la vez.</p>
</li>
</ol>
<p>Sigue, en el siguiente post, un episodio que ya rozó al Post 1 pero merece su propio tratamiento: <em>"La disciplina manual antes del patrón"</em> (<code>H-11</code>). Cómo Sentinel manejó <code>CHARTER-18</code> antes de que existiera el <code>Pattern 1</code> de chain evolution — el aprendizaje empírico que el <code>Post 1</code> después nombró como meta-patrón.</p>
<hr>
<p><em>Anclas: PR <a href="https://github.com/StrangeDaysTech/straymark/pull/142" target="_blank" rel="noopener noreferrer" class="">#142</a>. Releases: <code>fw-4.13.3</code> / <code>cli-3.12.3</code>. Commit clave: <code>a8a1ac5</code>. Archivos: <code>dist/.straymark/audit-prompts/audit-prompt.md</code> (EN canonical) + <code>dist/.straymark/audit-prompts/i18n/es/audit-prompt.md</code> (overlay). CLI: <code>cli/src/commands/charter/audit.rs</code> cableado al resolver i18n.</em></p>
<p><em>Este documento fue elaborado con asistencia de herramientas de IA generativa (Claude 4.7); toda la responsabilidad del contenido recae en el autor humano.</em></p>]]></content:encoded>
            <category>straymark</category>
            <category>i18n</category>
            <category>audit</category>
            <category>governance</category>
        </item>
        <item>
            <title><![CDATA[TDE y la deuda transversal]]></title>
            <link>https://straymark.dev/es/blog/tde-and-transversal-debt</link>
            <guid>https://straymark.dev/es/blog/tde-and-transversal-debt</guid>
            <pubDate>Tue, 12 May 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[El tipo existía. El trigger no. Y la lección stacked-PR que llegó de regalo.]]></description>
            <content:encoded><![CDATA[<p><em>Cero TDEs en trece Charters cerrados de Sentinel, a pesar de al menos siete piezas reconocibles de deuda transversal. El tipo documental existía; el trigger operacional no. Cómo fw-4.13.0 cerró el hueco — y cómo su cadena de PRs codificó accidentalmente una lección sobre stacked PRs.</em></p>
<!-- -->
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="1-cero-tdes-en-trece-charters">1. Cero TDEs en trece Charters<a href="https://straymark.dev/es/blog/tde-and-transversal-debt#1-cero-tdes-en-trece-charters" class="hash-link" aria-label="Enlace directo al 1. Cero TDEs en trece Charters" title="Enlace directo al 1. Cero TDEs en trece Charters" translate="no">​</a></h2>
<p>El Issue <a href="https://github.com/StrangeDaysTech/straymark/issues/128" target="_blank" rel="noopener noreferrer" class="">#128</a> abre con una asimetría inquietante:</p>
<blockquote>
<p><em>"Sentinel adopter (primary, fw-4.12.0) created zero TDEs across 13 closed Charters despite ≥7 instances of transversal debt routed through parallel mechanisms."</em></p>
</blockquote>
<p>Trece Charters cerrados. Al menos siete piezas reconocibles de deuda transversal — heredada de Charters anteriores, atravesando módulos, persistente entre sesiones. Cero TDEs. Si el operador hubiera estado discutiendo cumplir cuotas, el dato no significaría nada. Pero el operador era yo y el adoptante era el mismo proyecto que valida empíricamente el framework. Si Sentinel — el repo donde más se intentó usar el framework completo — no producía TDEs ni una vez en trece intentos, había algo roto.</p>
<p>Lo roto no era la deuda, que estaba siendo capturada por otros canales (<code>R&lt;N&gt; (new, not in Charter)</code> dentro de los AILOGs, entradas en <code>follow-ups-backlog.md</code>). Lo roto era que ningún criterio del framework decía <em>"esta pieza concreta merece TDE, no R<n>"</n></em>. El tipo de documento existía. El trigger operativo, no.</p>
<p>Este post cubre el episodio del 11-12 de mayo de 2026: cómo se diagnosticó la falta del trigger, cómo se cerró con cuatro criterios canónicos (<code>fw-4.13.0</code>), y cómo el ciclo de PRs que arregló el problema dejó al pasar una lección operativa sobre stacked-PRs que terminó codificada en el <code>CLAUDE.md</code> del proyecto. Es el primer episodio del blog donde el framework arregla <em>dos cosas distintas</em> en el mismo arco, y donde la segunda es accidental.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="2-el-tipo-existía-el-trigger-no">2. El tipo existía. El trigger no.<a href="https://straymark.dev/es/blog/tde-and-transversal-debt#2-el-tipo-exist%C3%ADa-el-trigger-no" class="hash-link" aria-label="Enlace directo al 2. El tipo existía. El trigger no." title="Enlace directo al 2. El tipo existía. El trigger no." translate="no">​</a></h2>
<p><code>TDE</code> — <em>Technical Debt Entry</em> — existe en el framework desde el primer commit de enero (Post 2 lo registra: estaba en la lista de ocho tipos originales del README v1.0.0). El template estaba. El campo en la taxonomía estaba. La carpeta <code>06-evolution/technical-debt/</code> estaba.</p>
<p>Lo que no estaba era una frase, en algún sitio del aparato canónico, que dijera <em>"crea un TDE ahora"</em>. El Issue #128 lo formuló sin atenuar:</p>
<blockquote>
<p><em>"Reading the adopter-facing docs (<code>AGENT-RULES.md</code>, <code>DOCUMENTATION-POLICY.md</code>, <code>QUICK-REFERENCE.md</code>, <code>CLAUDE.md</code> autonomous rules), there is no clear trigger that says 'create a TDE now'. The trigger language exists for AILOG (creation freely), AIDEC (when alternatives considered), ETH (high risk PII), ADR (architectural decisions), but TDE is just listed as 'agent can Identify'."</em></p>
</blockquote>
<p><em>"Agent can identify."</em> Identifica si quiere. Un agente entrando al repo lee esa línea, encoge los hombros, y sigue con AILOG y AIDEC, que sí le dicen <em>cuándo</em>. El defecto es el mismo del Issue #113 (Post 5): el artefacto técnicamente existe, pero la <em>superficie</em> canónica no le da al agente el verbo necesario para activarlo. Lo que diferencia este caso del #113 es la consecuencia. Para Charters, no verlos significaba no usar el flujo nuevo. Para TDE, no verlos significaba mucho peor: la deuda transversal <em>se capturaba</em> — pero fragmentada, sin vista consolidada, sin priorización entre artefactos, sin campo <code>assigned_to</code> ni <code>priority</code> para que un revisor humano pudiera ordenarla.</p>
<p>El Issue cita esa consecuencia con un nivel de detalle que da vergüenza, porque enumera todo lo que no estaba ocurriendo:</p>
<blockquote>
<p><em>"No queryable 'all open technical debts' view at the document level. No <code>impact × effort</code> prioritization matrix per item. No <code>assigned_to</code> / <code>priority</code> fields surfaced to the human reviewer. Architectural debt that legitimately spans multiple charters (e.g., scope authorization gap heritage across modules) gets fragmented into per-charter R-numbers instead of consolidated into a single TDE."</em></p>
</blockquote>
<p>Trece Charters de deuda fragmentada en <code>R&lt;N&gt;</code> per-Charter. Vista del operador del repo: ninguna lista consolidada, ninguna heredada explícitamente nombrada como tal, ninguna pieza de deuda priorizable a nivel de proyecto. Todo estaba en el repo. Nada estaba en el sitio que el repo construye para los humanos que vienen a leerlo de afuera.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="3-cuatro-criterios-para-una-pieza-de-deuda">3. Cuatro criterios para una pieza de deuda<a href="https://straymark.dev/es/blog/tde-and-transversal-debt#3-cuatro-criterios-para-una-pieza-de-deuda" class="hash-link" aria-label="Enlace directo al 3. Cuatro criterios para una pieza de deuda" title="Enlace directo al 3. Cuatro criterios para una pieza de deuda" translate="no">​</a></h2>
<p>El PR <a href="https://github.com/StrangeDaysTech/straymark/pull/129" target="_blank" rel="noopener noreferrer" class="">#129</a> (<code>fw-4.13.0</code>, fusionado el 11 de mayo a las 19:38 UTC, exactamente 13 horas después de abrirse el Issue) cerró el hueco con una sección nueva en <code>AGENT-RULES.md §3</code> titulada <em>"TDE vs `R<n> (new, not in Charter)"</n></em>. Los cuatro criterios literales:</p>

























<table><thead><tr><th>Criterio</th><th>Cuándo aplica</th></tr></thead><tbody><tr><td><strong>1. Heritage from a prior Charter</strong></td><td>La deuda viene heredada literalmente del Charter anterior (<em>strict heritage</em>) o reaparece al seguir el patrón del Charter anterior (<em>pattern propagation</em>).</td></tr><tr><td><strong>2. Applies to multiple modules or Charter execution boundaries</strong></td><td>La deuda atraviesa módulos del código <em>o</em> atraviesa límites de ejecución entre Charters (governance-trail debt).</td></tr><tr><td><strong>3. Requires a dedicated Charter outside current scope</strong></td><td>Resolverla requiere abrir un Charter propio, fuera del envelope del Charter actual.</td></tr><tr><td><strong>4. Requires human prioritization/assignment</strong></td><td>Decidir prioridad o asignación está fuera del rango del agente.</td></tr></tbody></table>
<p>La regla operativa: si una pieza de deuda satisface <em>al menos uno</em> de los cuatro criterios, es TDE. Si no satisface ninguno, sigue siendo <code>R&lt;N&gt;</code> dentro del Charter donde apareció.</p>
<p>Los cuatro tienen su lógica. Heritage (1) captura la deuda que persiste a través del tiempo, lo que un revisor querría ver agrupado por origen, no por Charter. Multi-module o multi-Charter (2) captura la deuda que vive <em>entre</em> artefactos, no <em>dentro</em> de uno. Dedicated Charter (3) reconoce que algunas piezas de deuda son tan grandes que merecen su propio ciclo y, por tanto, no caben como riesgo declarado <em>ex-ante</em>. Human prioritization (4) reconoce el límite de autonomía: hay decisiones que el agente puede señalar pero no resolver, y esas decisiones merecen un documento donde un humano pueda hacer cola.</p>
<p>El mismo PR añadió un campo nuevo al frontmatter del template TDE — <code>promoted_from_followup: FU-NNN | null</code> — y una sección en <code>FOLLOW-UPS-BACKLOG-PATTERN.md</code> que documenta cómo ascender una entrada de follow-ups a TDE. La promoción tiene dos formas, ambas registradas literalmente: promoción de entrada existente (un follow-up que llevaba semanas en la lista madura a TDE) y <em>retropromotion at creation</em> (al crear el TDE se reconoce que originó en un follow-up anterior y se anota). El campo del frontmatter cierra el rastro: cualquier TDE puede ahora apuntar hacia atrás al follow-up que lo originó, si existió.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="4-tres-tdes-en-sentinel--el-loop-empírico-cerrado">4. Tres TDEs en Sentinel — el loop empírico cerrado<a href="https://straymark.dev/es/blog/tde-and-transversal-debt#4-tres-tdes-en-sentinel--el-loop-emp%C3%ADrico-cerrado" class="hash-link" aria-label="Enlace directo al 4. Tres TDEs en Sentinel — el loop empírico cerrado" title="Enlace directo al 4. Tres TDEs en Sentinel — el loop empírico cerrado" translate="no">​</a></h2>
<p>El Issue #128 no cerró por argumento; cerró por evidencia. El mismo día, Sentinel — el mismo adoptante que llevaba trece Charters sin un solo TDE — creó tres:</p>
<ul>
<li class="">Un TDE para una <strong>brecha arquitectónica de RequireScope</strong>, herencia que atravesaba módulos. Criterios 1 + 2 + 3.</li>
<li class="">Un TDE sobre <strong>cobertura de tests faltante en la capa HTTP</strong>, deuda que persistía a través de Charters de feature. Criterios 1 + 4.</li>
<li class="">Un TDE de <strong>revisión de AILOGs legacy</strong> anteriores al format v3 de Charter, una pieza que necesitaba su propio ciclo. Criterios 1 + 3.</li>
</ul>
<p>Tres documentos en horas. La velocidad importa menos que el hecho de que cada uno aplicó <em>al menos uno</em> de los criterios y ninguno cayó en zona gris. Los criterios funcionaron como heurística sin ambigüedad — el operador no tuvo que negociar consigo mismo sobre si una pieza era TDE o <code>R&lt;N&gt;</code>. El loop empírico que el Issue había abierto en la mañana cerró con tres documentos esa misma tarde.</p>
<p>El PR <a href="https://github.com/StrangeDaysTech/straymark/pull/136" target="_blank" rel="noopener noreferrer" class="">#136</a> (<code>fw-4.13.1</code>, fusionado al día siguiente) refinó dos criterios a partir de esa misma experiencia. <em>Heritage</em> (1) se desdobló explícitamente en <em>strict heritage</em> vs <em>pattern propagation</em> porque uno de los tres TDEs de Sentinel mostraba el segundo caso de forma clara: la deuda no era heredada literal, era el mismo patrón reaparecido al seguir el mismo procedimiento. <em>Multi-module</em> (2) se reformuló como <em>"multiple modules <strong>or Charter execution boundaries</strong>"</em> porque otro de los tres TDEs era de governance-trail (cruzaba límites de sesión sin cruzar módulos de código). Los criterios crecieron una sola refinement-pass después de ejercerse en tres casos reales. El framework volvió a validar el principio #12: ningún schema cristaliza sin un segundo dominio.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="5-la-lección-stacked-pr">5. La lección stacked-PR<a href="https://straymark.dev/es/blog/tde-and-transversal-debt#5-la-lecci%C3%B3n-stacked-pr" class="hash-link" aria-label="Enlace directo al 5. La lección stacked-PR" title="Enlace directo al 5. La lección stacked-PR" translate="no">​</a></h2>
<p>Aquí es donde el post se desvía con propósito. El arco de PRs #129 → #131 → #133 que cerró el Issue #128 dejó una lección operativa adyacente — no sobre TDE sino sobre cómo <em>no</em> hay que armar branches encadenadas. La lección está hoy documentada literal en <code>CLAUDE.md</code> (líneas 181-220) del repo público bajo la sección <strong>"Stacked PRs — avoid, or use merge commits"</strong>.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="cómo-se-rompió">Cómo se rompió<a href="https://straymark.dev/es/blog/tde-and-transversal-debt#c%C3%B3mo-se-rompi%C3%B3" class="hash-link" aria-label="Enlace directo al Cómo se rompió" title="Enlace directo al Cómo se rompió" translate="no">​</a></h3>
<p>PR #131 (<code>cli-3.12.1</code>, fix del validator que rechazaba <code>status: identified</code> en TDEs) se abrió con <code>base = #129</code> porque <code>#131</code> necesitaba el código de <code>#129</code> para compilar sus tests. Después, <code>#129</code> se fusionó a <code>main</code> con <em>squash</em>. El <code>CLAUDE.md</code> actual lo describe con una precisión que vale la pena citar entera:</p>
<blockquote>
<p><em>"When you stack PR B on top of PR A's branch (base of B is A's head, not <code>main</code>), and A is squash-merged to <code>main</code>, B's content gets stranded:</em></p>
<p><em>— The squash merge of A creates a new commit on <code>main</code> with content equivalent to A but a different SHA than A's original commits.</em></p>
<p><em>— B's branch still points at A's original commits, which now have no descendant on <code>main</code>.</em></p>
<p><em>— When B is merged, GitHub merges it into A's branch (its declared base), not <code>main</code>. The 'merge to main' never happens — even though GitHub UI shows B as MERGED."</em></p>
</blockquote>
<p>Resultado en la práctica del ciclo #129/#131: la UI de GitHub mostraba <code>#131</code> como <em>MERGED</em>, los tests del validator estaban en main aparentemente, pero el contenido nunca llegó. PR #133 fue el sync procedural que tuvo que abrirse después para llevar el contenido a su destino. Tiempo perdido en diagnóstico: alrededor de tres horas. Tiempo de la operación de recuperación una vez entendida: cinco minutos.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="cómo-se-previene">Cómo se previene<a href="https://straymark.dev/es/blog/tde-and-transversal-debt#c%C3%B3mo-se-previene" class="hash-link" aria-label="Enlace directo al Cómo se previene" title="Enlace directo al Cómo se previene" translate="no">​</a></h3>
<p>El <code>CLAUDE.md</code> documenta dos estrategias, una conservadora y una pragmática:</p>
<blockquote>
<p><em>"1. Sequential, not stacked. Wait for PR A to merge to <code>main</code>, then rebase B onto <code>main</code> and open B as a standalone PR with <code>base = main</code>. Slower but bulletproof.</em></p>
<p><em>2. If you must stack, use merge commits (not squash) for the parent. A merge commit preserves shared history, so subsequent merges of stacked PRs into <code>main</code> resolve cleanly. Pay the cost of a noisier <code>git log</code> for the stacked-PR safety."</em></p>
</blockquote>
<p>Sentinel y StrayMark por defecto usan squash. Esa elección es buena para tener un <code>git log</code> limpio, una decisión por feature, un commit por PR. Pero cuesta exactamente esto: incompatibilidad con stacked-PRs. La regla que el <code>CLAUDE.md</code> ahora codifica es honesta: o no apilas, o pagas en historia de commits para poder apilar. No hay tercera opción que no rompa algo.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="cómo-se-recupera-si-ya-pasó">Cómo se recupera (si ya pasó)<a href="https://straymark.dev/es/blog/tde-and-transversal-debt#c%C3%B3mo-se-recupera-si-ya-pas%C3%B3" class="hash-link" aria-label="Enlace directo al Cómo se recupera (si ya pasó)" title="Enlace directo al Cómo se recupera (si ya pasó)" translate="no">​</a></h3>
<p>La sección de recovery del <code>CLAUDE.md</code> es la pieza más operativa del documento. Cuatro pasos:</p>
<blockquote>
<p><em>"1. <code>git checkout -b chore/sync-&lt;B-content&gt;-to-main main</code></em></p>
<p><em>2. <code>git cherry-pick &lt;B's merge commit SHA&gt;</code> — should be clean because B touches files outside A's conflict zone (which is why it could be stacked in the first place).</em></p>
<p><em>3. Push, open PR with <code>base = main, head = chore/sync-...</code>. Cherry-pick produces a fresh commit on top of <code>main</code>, so no conflicts.</em></p>
<p><em>4. The branch protection may require <code>--admin</code> merge if the content was already reviewed in B (the original PR) — sync PRs are purely procedural."</em></p>
</blockquote>
<p>El último paso es importante editorial mente: nota explícita de que un merge <code>--admin</code> está autorizado <em>solo</em> para PRs procedurales como este — donde el contenido ya fue revisado en el PR original. Es la única excepción a la regla <em>"el contenido va por revisión humana"</em> del proyecto.</p>
<p>La razón por la que vale la pena registrar la lección como sub-sección del post sobre TDE — y no como post separado — es que comparten un rasgo: ambas son piezas de <strong>deuda transversal de proceso</strong> que el framework ahora nombra explícitamente. Una es deuda de código (TDE como tipo nuevo); la otra es deuda de workflow (stacked-PR como anti-patrón documentado). Las dos comparten origen: la fricción operativa real fue lo que disparó el documento.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="6-lo-que-el-episodio-dejó-en-el-repo">6. Lo que el episodio dejó en el repo<a href="https://straymark.dev/es/blog/tde-and-transversal-debt#6-lo-que-el-episodio-dej%C3%B3-en-el-repo" class="hash-link" aria-label="Enlace directo al 6. Lo que el episodio dejó en el repo" title="Enlace directo al 6. Lo que el episodio dejó en el repo" translate="no">​</a></h2>
<p>Cuatro PRs en menos de veinticuatro horas, tres lecciones registradas:</p>
<ul>
<li class=""><strong>PR <a href="https://github.com/StrangeDaysTech/straymark/pull/129" target="_blank" rel="noopener noreferrer" class="">#129</a></strong> (<code>fw-4.13.0</code>, 11 may 19:38 UTC) — TDE activation trigger. Cuatro criterios + sección nueva en <code>AGENT-RULES.md §3</code> + path FU → TDE.</li>
<li class=""><strong>PR <a href="https://github.com/StrangeDaysTech/straymark/pull/131" target="_blank" rel="noopener noreferrer" class="">#131</a></strong> (<code>cli-3.12.1</code>, 11 may 19:39 UTC) — validator acepta <code>status: identified</code> en TDEs. Sin el fix, el primer TDE creado bajo el nuevo trigger fallaba la validación.</li>
<li class=""><strong>PR <a href="https://github.com/StrangeDaysTech/straymark/pull/134" target="_blank" rel="noopener noreferrer" class="">#134</a></strong> (12 may 04:54 UTC) — la lección stacked-PR documentada en <code>CLAUDE.md</code>. No cambió código del framework; cambió las reglas operativas del repo.</li>
<li class=""><strong>PR <a href="https://github.com/StrangeDaysTech/straymark/pull/136" target="_blank" rel="noopener noreferrer" class="">#136</a></strong> (<code>fw-4.13.1</code>, 12 may 04:54 UTC) — refinamientos del trigger TDE basados en los tres casos reales de Sentinel.</li>
</ul>
<p>Lo que más me interesa señalar de la cronología: el <code>CLAUDE.md</code> (PR #134) se actualizó el mismo arco que cerró el Issue #128. La lección stacked-PR no esperó a olvidarse. Si la disciplina del framework es <em>"todo cambio significativo deja rastro documentado"</em>, eso aplica también a la fricción operativa, no solo al diseño. El framework existe, en parte, para que los aprendizajes caros no se evaporen.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="7-cierre">7. Cierre<a href="https://straymark.dev/es/blog/tde-and-transversal-debt#7-cierre" class="hash-link" aria-label="Enlace directo al 7. Cierre" title="Enlace directo al 7. Cierre" translate="no">​</a></h2>
<p>Lo que aprendí del proceso, en cuatro tesis:</p>
<ol>
<li class="">
<p><strong>Un tipo de documento sin trigger es un tipo invisible.</strong> Igual que en el Issue #113, lo que el agente no ve al entrar al repo no existe para él. TDE existía técnicamente desde enero, pero solo empezó a usarse cuando los cuatro criterios aparecieron en <code>AGENT-RULES.md §3</code>. Estructura sin verbo activador es decoración.</p>
</li>
<li class="">
<p><strong>La deuda transversal merece tipo propio.</strong> Fragmentar deuda en <code>R&lt;N&gt;</code> per-Charter destruye la propiedad más importante de un sistema de gobernanza: la vista consolidada. Cuatro criterios, cualquiera basta, sostienen la línea entre <em>este es riesgo del Charter</em> y <em>esto es deuda del proyecto</em>.</p>
</li>
<li class="">
<p><strong>Los aprendizajes operativos también se documentan.</strong> PR #134 actualizó el <code>CLAUDE.md</code> del proyecto el mismo día que la lección apareció. No es paranoia archivística; es la misma regla aplicada hacia los procesos: si la fricción te costó tres horas hoy, escribe la lección hoy.</p>
</li>
<li class="">
<p><strong>El framework crece tanto por features como por anti-patrones.</strong> Este episodio dejó un tipo nuevo (TDE como entidad operativa) <em>y</em> un anti-patrón documentado (stacked-PRs incompatibles con squash). Ambas cosas son material del framework, aunque solo una aparezca como bump de versión.</p>
</li>
</ol>
<p>Sigue, en el siguiente post, un episodio breve pero estructural: <em>"El audit-prompt en español era el outlier"</em> (<code>H-10</code>). Un detalle de convención i18n que reveló qué idioma estaba siendo el canónico — y por qué corregirlo cambió, sin proponérselo, cómo el framework piensa sobre traducción.</p>
<hr>
<p><em>Anclas: <a href="https://github.com/StrangeDaysTech/straymark/issues/128" target="_blank" rel="noopener noreferrer" class="">Issue #128</a>. PRs <a href="https://github.com/StrangeDaysTech/straymark/pull/129" target="_blank" rel="noopener noreferrer" class="">#129</a> · <a href="https://github.com/StrangeDaysTech/straymark/pull/131" target="_blank" rel="noopener noreferrer" class="">#131</a> · <a href="https://github.com/StrangeDaysTech/straymark/pull/134" target="_blank" rel="noopener noreferrer" class="">#134</a> · <a href="https://github.com/StrangeDaysTech/straymark/pull/136" target="_blank" rel="noopener noreferrer" class="">#136</a>. Releases: <code>fw-4.13.0</code> / <code>cli-3.12.1</code> / <code>fw-4.13.1</code>. Lección stacked-PR codificada en <a href="https://github.com/StrangeDaysTech/straymark/blob/main/CLAUDE.md" target="_blank" rel="noopener noreferrer" class=""><code>CLAUDE.md</code> líneas 181-220</a> del repo.</em></p>
<p><em>Este documento fue elaborado con asistencia de herramientas de IA generativa (Claude 4.7); toda la responsabilidad del contenido recae en el autor humano.</em></p>]]></content:encoded>
            <category>straymark</category>
            <category>tde</category>
            <category>deuda-técnica</category>
            <category>governance</category>
            <category>git-workflow</category>
        </item>
        <item>
            <title><![CDATA[Validate y los schemas como capa formal]]></title>
            <link>https://straymark.dev/es/blog/validate-and-schemas-as-a-formal-layer</link>
            <guid>https://straymark.dev/es/blog/validate-and-schemas-as-a-formal-layer</guid>
            <pubDate>Mon, 11 May 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[Phase 2: cuando el framework empieza a verificar lo que prometía]]></description>
            <content:encoded><![CDATA[<p><em>464 líneas de bash reemplazadas por una flag. De "verifico que esto parezca un documento" a "verifico que esto satisface el schema canónico, en el modo que pidas, con consecuencias operacionales concretas." Fase 2 del roadmap del CLI y la formalización de validate.</em></p>
<!-- -->
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="1-tener-schemas-no-es-lo-mismo-que-validar-contra-schemas">1. Tener schemas no es lo mismo que validar contra schemas<a href="https://straymark.dev/es/blog/validate-and-schemas-as-a-formal-layer#1-tener-schemas-no-es-lo-mismo-que-validar-contra-schemas" class="hash-link" aria-label="Enlace directo al 1. Tener schemas no es lo mismo que validar contra schemas" title="Enlace directo al 1. Tener schemas no es lo mismo que validar contra schemas" translate="no">​</a></h2>
<p><code>straymark validate</code> existía desde el 25 de marzo de 2026 — PR #27, parte del primer arco de Phase 1 del CLI. Lo que hacía entonces era pequeño: verificar que los documentos en <code>.straymark/</code> tuvieran sintaxis Markdown válida, frontmatter parseable, y los campos mínimos del tipo correcto. Era útil. No era <em>enforcement</em>.</p>
<p>Lo que cambió el 11 de mayo de 2026, con el release <code>fw-4.6.0 / cli-3.7.0</code>, fue otra cosa: Phase 2 del roadmap del CLI cerró un arco completo de siete PRs (#73 a #79) y los consolidó en uno solo (#80). El CHANGELOG lo dice sin metáfora:</p>
<blockquote>
<p><em>"The first feature-bearing release since the repositioning... Phase 2 of <code>Propuesta/devtrail-cli-roadmap.md</code> lands as 7 bisect-safe PRs (#73–#79), grouped here for reviewers. The release closes the empirical loop the Sentinel experiment opened: telemetry at Charter close, drift detection at Charter close, and a canonical approval signal for <code>review_required: true</code> documents."</em></p>
</blockquote>
<p>Lo que importa para este post no son los siete PRs como hitos individuales; son los tres que tocaron el comando <code>validate</code> y los schemas. Lo que en marzo era <em>"verifico que esto parece un documento"</em> en mayo se volvió <em>"verifico que esto cumple el schema canónico del tipo, en el modo que pidas, con consecuencias operativas concretas"</em>.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="2-del-bash-artesanal-al-flag-de-comando">2. Del bash artesanal al flag de comando<a href="https://straymark.dev/es/blog/validate-and-schemas-as-a-formal-layer#2-del-bash-artesanal-al-flag-de-comando" class="hash-link" aria-label="Enlace directo al 2. Del bash artesanal al flag de comando" title="Enlace directo al 2. Del bash artesanal al flag de comando" translate="no">​</a></h2>
<p>Una de las piezas más visibles del cambio es pequeña: el flag <code>--staged</code>.</p>
<p>Hasta Phase 2, el patrón recomendado para que los adoptantes validaran sus documentos antes de un commit era un script bash llamado <code>pre-commit-docs.sh</code>. Vivía en <code>dist/.straymark/scripts/</code> y tenía 464 líneas. Hacía lo razonable: leer <code>git diff --cached --name-only</code>, filtrar archivos en <code>.straymark/</code>, parsear su frontmatter con <code>awk</code>, verificar campos. Funcionaba. Y era 464 líneas de bash que cada adoptante tenía que confiar en que ejecutaba lo correcto, en su versión correcta, con su parser de YAML correcto.</p>
<p>PR del 28 de marzo (commit <code>d9ea874</code>) reemplazó las 464 líneas por un flag:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">straymark validate </span><span class="token parameter variable" style="color:#36acaa">--staged</span><br></div></code></pre></div></div>
<p>Lee los staged files igual, filtra por <code>.straymark/</code> igual, valida igual. La diferencia: hoy todo eso vive en Rust dentro del binario, no en bash en disco. El adoptante no tiene que mantener el script; el script no puede divergir entre versiones; el comportamiento es el mismo en Linux, macOS y Windows. El framework dejó de pedirle al adoptante que confiara en un script suelto y empezó a darle un comando con la promesa implícita del binario versionado.</p>
<p>Es el mismo patrón que el Post 6 documentó para la disciplina de archivo (preservar git history en lugar de reescribir) o que el Post 4 documentó con la decisión A1 (orquestar sin invocar APIs): pasar de <em>"el operador hace X manualmente con riesgo de divergir"</em> a <em>"el framework canoniza X en un comando declarativo"</em>. El <code>--staged</code> no es feature exótico; es deuda manual barrida.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="3-los-tres-schemas-v0">3. Los tres schemas v0<a href="https://straymark.dev/es/blog/validate-and-schemas-as-a-formal-layer#3-los-tres-schemas-v0" class="hash-link" aria-label="Enlace directo al 3. Los tres schemas v0" title="Enlace directo al 3. Los tres schemas v0" translate="no">​</a></h2>
<p>Phase 2 también consolidó los tres schemas que viven en <code>dist/.straymark/schemas/</code>:</p>

























<table><thead><tr><th>Schema</th><th>Qué describe</th><th>Origen</th></tr></thead><tbody><tr><td><code>charter.schema.v0.json</code></td><td>Estructura del Charter como entidad de primera clase (Post 4)</td><td>Sentinel <code>/plan-audit</code> (6 ciclos, format v1 → v2 → v3)</td></tr><tr><td><code>charter-telemetry.schema.v0.json</code></td><td>Telemetría de Charters (Post 3, ampliado en Post 10)</td><td>5 archivos <code>PLAN-NN.telemetry.yaml</code> de Sentinel</td></tr><tr><td><code>audit-output.schema.v0.json</code></td><td>Output canónico de auditoría externa (Post 4 + Post 10)</td><td>Sentinel dual-audit (Copilot + Gemini + Claude crítico)</td></tr></tbody></table>
<p>Cada schema lleva un campo <code>$comment</code> en su raíz. El de <code>charter.schema.v0.json</code> dice literal:</p>
<blockquote>
<p><em>"EXPERIMENTAL v0. Crystallized from Sentinel /plan-audit (6 cycles, format v1 → v2 → v3). Will not stabilize to v1.0 until validated in a second domain (frontend, ML pipeline, or infra-as-code)."</em></p>
</blockquote>
<p>El de <code>charter-telemetry.schema.v0.json</code>, parecido:</p>
<blockquote>
<p><em>"EXPERIMENTAL v0. Derived from 5 PLAN-NN.telemetry.yaml files in Sentinel (one project, Go backend) — same N=1-domain caveat as charter.schema.v0.json. Will not stabilize to v1.0 until validated in a second domain."</em></p>
</blockquote>
<p>El de <code>audit-output.schema.v0.json</code>, idem:</p>
<blockquote>
<p><em>"EXPERIMENTAL v0.x. Phase 3 of the CLI roadmap. Crystallized from the dual-audit pattern validated empirically in Sentinel."</em></p>
</blockquote>
<p>Los tres comparten una declaración explícita: <em>no crystallizes without a second domain</em>. Es el principio #12 del framework, no como párrafo aparte en una documentación de gobernanza, sino <strong>dentro del propio JSON Schema, en un campo que cualquier validador estándar lee y cualquier herramienta de schema-explorer renderiza al usuario</strong>. El framework no esconde la provisionalidad de sus schemas; la pone donde nadie pueda perderla.</p>
<p>Esto importa más de lo que parece. La práctica habitual en ecosistemas de schemas (JSON Schema, OpenAPI, Avro) es publicar <code>v1</code> y luego bumpear conforme cambias. Marcar <code>v0</code> con un <code>$comment</code> que dice <em>"esto es experimental hasta que un segundo dominio lo valide"</em> es admitir, de origen, que la primera cristalización no es la definitiva. La schema misma es honesta.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="4-tres-modos-del-comando">4. Tres modos del comando<a href="https://straymark.dev/es/blog/validate-and-schemas-as-a-formal-layer#4-tres-modos-del-comando" class="hash-link" aria-label="Enlace directo al 4. Tres modos del comando" title="Enlace directo al 4. Tres modos del comando" translate="no">​</a></h2>
<p><code>straymark validate</code> ya no es un comando con un solo flujo. Después de Phase 2 tiene tres modos operativos, cada uno acoplado a un momento del ciclo de vida:</p>
<ul>
<li class="">
<p><strong>Modo <code>all</code> (default)</strong> — <code>straymark validate</code> sin flags. Camina recursivamente <code>.straymark/</code>, parsea cada archivo <code>.md</code>, intenta resolver su tipo (AILOG, AIDEC, ADR, ETH, REQ, TES, INC, TDE, MCARD, SBOM, SEC, DPIA, Charter), aplica el schema correspondiente, y reporta violaciones por archivo. Es el modo <em>auditoría completa</em>. Útil para CI, útil para revisar un repo nuevo, útil cuando el adoptante quiere medir cuánta deuda formal acumuló.</p>
</li>
<li class="">
<p><strong>Modo <code>--staged</code></strong> — <code>straymark validate --staged</code>. El que reemplazó al bash. Solo valida archivos que <code>git diff --cached --name-only</code> reporta como staged dentro de <code>.straymark/</code>. Su lugar natural es <code>.git/hooks/pre-commit</code>, y desde fw-4.6.0 hay un <code>straymark init --hooks</code> que lo instala automáticamente. Es el modo <em>gate operativo</em> — el que evita que documentos rotos lleguen a <code>main</code>.</p>
</li>
<li class="">
<p><strong>Modo <code>--check-pending-reviews</code></strong> — <code>straymark validate --check-pending-reviews</code>. El más sutil de los tres, y el que justifica más párrafos.</p>
</li>
</ul>
<p>Hasta Phase 2, un documento que el agente marcaba <code>review_required: true</code> en el frontmatter (un AIDEC con confianza baja, un AILOG con riesgo alto, etc.) quedaba esperando <em>aprobación humana</em>. Pero no había una forma canónica de <em>señalar</em> esa aprobación. El operador leía el documento, mentalmente lo aprobaba, seguía. No quedaba rastro estructural de la aprobación. Esto era exactamente el Issue <a href="https://github.com/StrangeDaysTech/straymark/issues/67" target="_blank" rel="noopener noreferrer" class="">#67</a>.</p>
<p><code>--check-pending-reviews</code> cierra ese hueco. El comando recorre todos los documentos con <code>review_required: true</code> y los listsa con su <code>confidence</code>, su <code>risk_level</code>, su autor (humano o agente), y su fecha. La aprobación es un commit que cambia <code>review_required: true</code> → <code>review_required: false</code> con co-autoría humana en el commit message — y <code>validate --check-pending-reviews</code> deja de listar el documento. La aprobación es un <em>signal canónico</em>, no un acuerdo verbal con uno mismo.</p>
<p>Es la pieza que cierra el ciclo del agente. El framework permite al agente crear documentos sin pre-aprobación humana (Post 1, propiedad #2: <em>"permiso cultural sin control bloqueante"</em>); pero los marca para revisión cuando corresponde; y ahora tiene un comando para listar lo pendiente, sin escapatoria. Ningún documento de auditoría se pierde en silencio.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="5-phase-2-cierra-el-loop-empírico">5. Phase 2 cierra el loop empírico<a href="https://straymark.dev/es/blog/validate-and-schemas-as-a-formal-layer#5-phase-2-cierra-el-loop-emp%C3%ADrico" class="hash-link" aria-label="Enlace directo al 5. Phase 2 cierra el loop empírico" title="Enlace directo al 5. Phase 2 cierra el loop empírico" translate="no">​</a></h2>
<p>Vale la pena rescatar la frase del CHANGELOG entera porque condensa lo que el release significa:</p>
<blockquote>
<p><em>"The release closes the empirical loop the Sentinel experiment opened: telemetry at Charter close, drift detection at Charter close, and a canonical approval signal for <code>review_required: true</code> documents (resolving issue #67)."</em></p>
</blockquote>
<p>Tres piezas que cierran un arco que arrancó en el experimento de los seis Planes (Post 3):</p>
<ol>
<li class=""><strong>Telemetría al cierre del Charter</strong> — el bloque YAML que Sentinel llenaba a mano durante el experimento se convirtió en el schema <code>charter-telemetry.schema.v0.json</code> validable.</li>
<li class=""><strong>Drift detection al cierre del Charter</strong> — el script bash de 145 líneas (<code>check-plan-drift.sh</code>) se convirtió en el subcomando <code>straymark charter drift</code>, integrado al validate flow.</li>
<li class=""><strong>Approval signal canónico</strong> — lo que el operador hacía mentalmente se convirtió en un comando con consecuencias estructurales: <code>--check-pending-reviews</code>.</li>
</ol>
<p>Es el patrón que el blog ha visto repetirse: cada vez que el framework cristaliza una práctica que Sentinel hacía manualmente, lo hace después de validar empíricamente que la práctica funciona. La diferencia esta vez es que <strong>el comando que verifica la cristalización es parte del paquete</strong>. Antes del Phase 2, Sentinel tenía templates, schemas declarados, y la promesa implícita de que los documentos seguían los schemas. Después de Phase 2, hay un comando que <strong>lo comprueba</strong>. No es un cambio de capacidad; es un cambio de garantías.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="6-el-principio-12-hecho-schema">6. El principio #12, hecho schema<a href="https://straymark.dev/es/blog/validate-and-schemas-as-a-formal-layer#6-el-principio-12-hecho-schema" class="hash-link" aria-label="Enlace directo al 6. El principio #12, hecho schema" title="Enlace directo al 6. El principio #12, hecho schema" translate="no">​</a></h2>
<p>La pieza filosófica del post — y la que más me interesa dejar registrada — es esta:</p>
<p>Los <code>$comment</code> de los tres schemas v0 codifican un principio que el framework venía declarando en prosa desde abril. El Post 4 lo nombró así: <em>"schema marked <code>v0</code> on purpose, not <code>v1</code>, because the framework's principle #12 says no schema crystallizes without a second domain validating it"</em>. El Post 7 lo aplicó al diseño del TDE: <em>"the framework validated principle #12 again: no schema crystallizes without a second domain"</em>. El Post 10 lo aplicó a Pattern 1 y Pattern 2: <em>"the document says so without shortcuts: the pattern is empirically validated in Sentinel. Wait for the second domain before crystallizing it higher"</em>.</p>
<p>Phase 2 hace algo distinto. <strong>No declara el principio; lo escribe dentro del schema mismo, en un lugar que cualquier consumidor del schema va a leer.</strong> El <code>$comment</code> no es marketing; es protocolo. Cualquier validador de JSON Schema 2020-12 lo expone; cualquier IDE que parsea el schema lo muestra. Es la primera vez que el framework formaliza la provisionalidad de sus formalizaciones.</p>
<p>Si quisiera resumirlo en una sola frase: el framework valida lo que tiene, sabiendo que lo que tiene es provisional, y deja eso por escrito <em>en el lugar donde la validación ocurre</em>. Validar lo provisional es disciplina. Cristalizar prematuramente y validar lo cristalizado es teología.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="7-cierre">7. Cierre<a href="https://straymark.dev/es/blog/validate-and-schemas-as-a-formal-layer#7-cierre" class="hash-link" aria-label="Enlace directo al 7. Cierre" title="Enlace directo al 7. Cierre" translate="no">​</a></h2>
<p>Lo que aprendí del proceso, en cuatro tesis:</p>
<ol>
<li class="">
<p><strong>Tener schemas no es lo mismo que validar contra schemas.</strong> El primer paso es declarativo; el segundo es operativo. Phase 2 hizo el segundo, no el primero. La diferencia entre los dos modos del framework — <em>"tengo la promesa"</em> vs. <em>"tengo el comando que la comprueba"</em> — es lo que determina si el adoptante puede confiar en lo declarado.</p>
</li>
<li class="">
<p><strong>El patrón "bash artesanal → flag de comando" es estructural.</strong> El <code>--staged</code> no es feature aislado. Es la versión Phase 2 del mismo patrón que Post 4 documentó para el audit cycle externo, que Post 10 documentó para los CLI helpers de chain evolution: imperativo verboso → declarativo legible → versionado. Cada vez que el framework barre un script bash por un flag, sube una capa de garantías.</p>
</li>
<li class="">
<p><strong>El <code>--check-pending-reviews</code> cierra el ciclo del agente.</strong> Lo que Post 1 nombró como permiso cultural sin pre-aprobación se completa aquí: el agente puede crear, pero los documentos marcados para revisión no se pierden — el comando los lista hasta que un humano los apruebe con un commit explícito. Sin ese signal, el permiso cultural del Post 1 sería negligencia.</p>
</li>
<li class="">
<p><strong>Provisionalidad declarada &gt; formalización prematura.</strong> Los <code>$comment</code> de los schemas v0 hacen el principio #12 protocolo, no doctrina. Cualquier herramienta que consuma el schema sabe que la formalización es provisional. Es la honestidad estructural más fuerte que puede tener un framework joven: validar lo que tiene, sin pretender que lo tenido es definitivo.</p>
</li>
</ol>
<hr>
<p><em>Anclas: PR <a href="https://github.com/StrangeDaysTech/straymark/pull/27" target="_blank" rel="noopener noreferrer" class="">#27</a> — versión original de <code>validate</code> (marzo 2026). Phase 2: PRs #73 a #79 + PR <a href="https://github.com/StrangeDaysTech/straymark/pull/80" target="_blank" rel="noopener noreferrer" class="">#80</a> — <code>fw-4.6.0 / cli-3.7.0</code> (fusionado 2026-05-11). Schemas: <code>dist/.straymark/schemas/{charter,charter-telemetry,audit-output}.schema.v0.json</code>. <a href="https://github.com/StrangeDaysTech/straymark/issues/67" target="_blank" rel="noopener noreferrer" class="">Issue #67</a> — origen del <code>--check-pending-reviews</code>.</em></p>
<p><em>Este documento fue elaborado con asistencia de herramientas de IA generativa (Claude 4.7); toda la responsabilidad del contenido recae en el autor humano.</em></p>]]></content:encoded>
            <category>straymark</category>
            <category>validate</category>
            <category>schemas</category>
            <category>governance</category>
            <category>phase-2</category>
        </item>
        <item>
            <title><![CDATA[Charters invisibles para los agentes]]></title>
            <link>https://straymark.dev/es/blog/charters-invisible-to-agents</link>
            <guid>https://straymark.dev/es/blog/charters-invisible-to-agents</guid>
            <pubDate>Sat, 09 May 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[Issue #113 — la brecha entre tener un artefacto y que el agente lo vea]]></description>
            <content:encoded><![CDATA[<p><em>Seis horas de sesión con un agente capaz y todo el onboarding del framework cargado — y ni una vez se sugirieron los Charters. Cinco minutos para aplicarlos al pedirlos directamente. La asimetría no es de capacidad; es de visibilidad.</em></p>
<!-- -->
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="1-seis-horas-para-no-verlo-cinco-minutos-para-verlo">1. Seis horas para no verlo, cinco minutos para verlo<a href="https://straymark.dev/es/blog/charters-invisible-to-agents#1-seis-horas-para-no-verlo-cinco-minutos-para-verlo" class="hash-link" aria-label="Enlace directo al 1. Seis horas para no verlo, cinco minutos para verlo" title="Enlace directo al 1. Seis horas para no verlo, cinco minutos para verlo" translate="no">​</a></h2>
<p>El Issue <a href="https://github.com/StrangeDaysTech/straymark/issues/113" target="_blank" rel="noopener noreferrer" class="">#113</a> abre con una de esas frases que, cuando uno la lee de regreso meses después, suena obvia y al mismo tiempo costó mucho llegar:</p>
<blockquote>
<p><em>"Time to detect: ~6 hours of session work; never autonomously surfaced. Time to resolve once user prompted: ~5 minutes."</em></p>
</blockquote>
<p>Seis horas trabajando con un agente capaz, atento, con todo el aparato canónico de onboarding del framework cargado — <code>STRAYMARK.md</code>, la constitución del proyecto, el checklist de <code>CLAUDE.md</code>, las skills <code>/straymark-*</code> disponibles, <code>/straymark-status</code> ejecutado al inicio — y nunca, en seis horas, el agente sugirió usar un Charter. Cuando se lo pedí directamente, el flujo se incorporó en cinco minutos. La asimetría no es de capacidad. Es de visibilidad.</p>
<p>Este post cubre un episodio corto y específico: el Issue #113, abierto el 7 de mayo de 2026, tres días después de que Charters se cristalizaran como entidad de primera clase del framework (fw-4.4.0, 2 de mayo). Es el contrapeso natural del primer post del blog. Aquel post nombró una propiedad que apareció cuando todo estaba en su sitio. Este post documenta lo que pasa cuando una pieza estructural existe pero <em>no está en la superficie que el agente lee primero</em>.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="2-el-experimento-accidental">2. El experimento accidental<a href="https://straymark.dev/es/blog/charters-invisible-to-agents#2-el-experimento-accidental" class="hash-link" aria-label="Enlace directo al 2. El experimento accidental" title="Enlace directo al 2. El experimento accidental" translate="no">​</a></h2>
<p>El setup no estaba pensado como experimento. Era un proyecto real: un <em>greenfield</em> en Rust, suite CLI+TUI, en su primera versión <code>v0.1</code>. El agente era Claude Opus 4.7 con ventana de 1M tokens, suficiente para tener todo el repo en contexto sin tener que paginar. El flujo era el canónico de SpecKit: <code>/speckit-specify</code>, <code>/speckit-plan</code>, <code>/speckit-tasks</code>, y entre tasks e implement debía aparecer — <em>en teoría</em> — la idea de cortar en Charters.</p>
<p>El Issue lo formula con precisión casi fría:</p>
<blockquote>
<p><em>"A capable, attentive agent following the canonical project onboarding (<code>DEVTRAIL.md</code>, the project constitution, <code>CLAUDE.md</code> checklist, available <code>/devtrail-*</code> skills, <code>/devtrail-status</code>) did not autonomously identify Charters as a workflow concept during plan/tasks generation, even though the project clearly fit their use case (multi-session implementation, multi-phase tasks, audit value)."</em></p>
</blockquote>
<p><em>(El Issue todavía usa <code>DEVTRAIL.md</code> porque, recordando la cronología, el rebrand a StrayMark estaba siendo merged casi al mismo tiempo. La nomenclatura mixta es residuo del calendario, no descuido.)</em></p>
<p>El proyecto cumplía cada una de las condiciones donde un Charter es la unidad correcta: implementación multi-sesión, varias fases, valor de auditoría. El agente hizo todo bien — leyó la constitución, ejecutó status, identificó skills disponibles, generó un plan de SpecKit razonable — y nunca conectó con Charters. Como si el concepto no existiera. Para él, en su modelo del repo, no existía.</p>
<p>Lo más incómodo del Issue, mirado desde mayo, es que el agente no falló por incapacidad. Falló porque el framework, sin proponérselo, le había construido un mapa en el que los Charters no aparecían marcados.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="3-nueve-gaps-que-convergen-en-uno">3. Nueve gaps que convergen en uno<a href="https://straymark.dev/es/blog/charters-invisible-to-agents#3-nueve-gaps-que-convergen-en-uno" class="hash-link" aria-label="Enlace directo al 3. Nueve gaps que convergen en uno" title="Enlace directo al 3. Nueve gaps que convergen en uno" translate="no">​</a></h2>
<p>Cuando el operador (yo) abrió el Issue y se sentó a auditar por qué había pasado, el problema no era una cosa. Eran nueve. Y todas eran versiones del mismo defecto:</p>























































<table><thead><tr><th>#</th><th>Gap</th><th>Dónde</th></tr></thead><tbody><tr><td>1</td><td>El documento canónico del framework no listaba Charter como concepto</td><td><code>STRAYMARK.md</code> (entonces <code>DEVTRAIL.md</code>) §6/9/10/11/13/15</td></tr><tr><td>2</td><td>El checklist de <code>CLAUDE.md</code> no tenía trigger para sugerir Charter</td><td><code>dist/dist-templates/directives/CLAUDE.md</code> (y <code>GEMINI.md</code>, <code>copilot-instructions.md</code>)</td></tr><tr><td>3</td><td>Las constituciones de proyecto heredan la brecha del framework</td><td>Cualquier <code>*-constitution.md</code> instalado vía <code>straymark init</code></td></tr><tr><td>4</td><td>No existía skill <code>/straymark-charter-new</code></td><td>Skills directory</td></tr><tr><td>5</td><td><code>/straymark-status</code> no listaba Charters en su output</td><td>Skill + CLI subcommand <code>straymark status</code></td></tr><tr><td>6</td><td>Las skills de auditoría hablaban del Charter como artefacto <em>externo</em>, no como superficie a generar</td><td><code>/straymark-audit-*</code> skills</td></tr><tr><td>7</td><td>Los templates de Charter convivían indistinguibles con otros templates</td><td><code>dist/.straymark/templates/</code> (raíz)</td></tr><tr><td>8</td><td>No había puente conceptual entre SpecKit (<code>plan.md</code>) y Charter</td><td>Ningún documento explícito</td></tr><tr><td>9</td><td>El modelo mental que el agente terminaba construyendo era binario: o SpecKit, o nada</td><td>Efecto compuesto</td></tr></tbody></table>
<p>Nueve fallas y un solo defecto: el Charter existía como artefacto técnico (schema válido, comando funcional, template portado de Sentinel), pero no estaba nombrado en ninguno de los lugares donde el agente construye su modelo mental del proyecto al entrar.</p>
<p>El agente lee el <code>STRAYMARK.md</code> y la constitución para entender de qué trata el proyecto. Si Charter no aparece, no está. El agente revisa qué skills tiene disponibles para usar. Si no hay <code>/straymark-charter-new</code>, no está. El agente corre <code>/straymark-status</code> para entender qué tipos de archivo viven en el repo. Si la salida no menciona Charters, no están. Cada superficie por la que el agente pasa al onboarding repite el mismo silencio. Y la suma de silencios convence al agente de que el concepto no es parte de este proyecto.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="4-por-qué-este-episodio-importa-más-allá-del-issue">4. Por qué este episodio importa más allá del Issue<a href="https://straymark.dev/es/blog/charters-invisible-to-agents#4-por-qu%C3%A9-este-episodio-importa-m%C3%A1s-all%C3%A1-del-issue" class="hash-link" aria-label="Enlace directo al 4. Por qué este episodio importa más allá del Issue" title="Enlace directo al 4. Por qué este episodio importa más allá del Issue" translate="no">​</a></h2>
<p>Vale la pena hacer una pausa aquí, porque este es exactamente el episodio que el meta-patrón de fw-4.17.0 — el patrón de <em>observación emergente</em> — necesitaba haber existido <em>antes</em> para poder formularse.</p>
<p>Una semana después de #113, en <code>EMERGENT-OBSERVATION-DESIGN.md</code>, el framework nombró dos propiedades cuya composición produce que el agente note cosas que nadie le pidió notar: vínculos formales entre artefactos (<code>originating_charter</code>, <code>originating_ailog</code>, <code>originating_spec</code> en frontmatter), y permiso cultural para señalar disonancias entre fuentes. Esas dos propiedades, <em>compuestas</em>, producen que el agente lea el AILOG, cuente las entradas <code>R&lt;N&gt;(new, not in Charter)</code>, y señale el delta sin que nadie se lo pida.</p>
<p>Pero hay un prerrequisito que esa formulación da por sentado: que el agente <em>vea</em> los Charters al entrar al repo. Si los Charters no están en la superficie visible, ningún vínculo formal entre artefactos puede componerse en observación emergente — porque uno de los términos de la composición no existe para el agente.</p>
<p>El Issue #113 es el episodio que documentó esa precondición desde la inversa. Fw-4.17.0 nombró el patrón cuando estaba presente; fw-4.12.0 (cinco días antes) cerró la brecha que impedía que estuviera presente en absoluto. Sin el Issue #113 y su corrección, el meta-patrón no tendría dónde apoyarse. El framework no señala lo que no ve, y no ve lo que la superficie no nombra.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="5-la-respuesta-multiplicar-superficies">5. La respuesta: multiplicar superficies<a href="https://straymark.dev/es/blog/charters-invisible-to-agents#5-la-respuesta-multiplicar-superficies" class="hash-link" aria-label="Enlace directo al 5. La respuesta: multiplicar superficies" title="Enlace directo al 5. La respuesta: multiplicar superficies" translate="no">​</a></h2>
<p>El PR <a href="https://github.com/StrangeDaysTech/straymark/pull/122" target="_blank" rel="noopener noreferrer" class="">#122</a> (<code>fw-4.12.0</code>, 9 de mayo) cubrió los nueve gaps con una sola estrategia operativa: <em>nombrar Charter en cada lugar donde el agente construye su modelo del proyecto</em>. Las cifras del PR son honestas: +1211 líneas, −92 líneas, 36 archivos modificados, casi todo documentación y plantillas. No hubo refactor de código. Hubo redistribución de visibilidad.</p>
<p>Cambios principales, agrupados:</p>
<ul>
<li class=""><strong>En el documento canónico</strong> (<code>STRAYMARK.md</code>): una sección nueva dedicada al Charter como concepto (§15), más filas en las tablas de §6/9/10/11/13 que listaban tipos de documento sin Charter.</li>
<li class=""><strong>En las directivas de agentes</strong> (<code>CLAUDE.md</code>, <code>GEMINI.md</code>, <code>copilot-instructions.md</code>): un trigger explícito que enseña al agente cuándo <em>sugerir</em> un Charter, no solo cuándo crearlo si se le pide.</li>
<li class=""><strong>En las skills</strong>: nueva <code>/straymark-charter-new</code> (versiones Claude, Gemini, agnóstica). <code>/straymark-status</code> actualizada para listar Charters activos.</li>
<li class=""><strong>En el CLI</strong>: bloque <code>Charters</code> añadido a la salida de <code>straymark status</code>, para que el agente que ejecuta el comando lo vea entre los signals iniciales.</li>
<li class=""><strong>En los templates</strong>: movidos a un subdirectorio dedicado <code>dist/.straymark/templates/charter/</code>, ya no mezclados con templates de otros tipos.</li>
<li class=""><strong>Documento nuevo</strong>: <code>SPECKIT-CHARTER-BRIDGE.md</code> (171 líneas, EN/ES/zh-CN). Hace explícito el puente entre el <code>plan.md</code> de SpecKit y el Charter de StrayMark — los cuatro criterios para que una feature de SpecKit produzca uno o varios Charters, los tres casos donde no aplica, las cuatro heurísticas de granularidad, el enlace de frontmatter <code>originating_spec ↔ originating_charter ↔ originating_ailog</code>.</li>
</ul>
<p>El epílogo de <code>SPECKIT-CHARTER-BRIDGE.md</code> registra el caso que originó todo el cambio sin metáfora:</p>
<blockquote>
<p><em>"Cited the empirical context (issue #113): Greenfield Rust CLI/TUI suite, Claude Opus 4.7 onboarding via canonical entry points. Charters were eventually adopted (2 Charters: foundation + MVP) only after explicit user prompt — confirming the gap was systemic, not session-specific. This document removes the gap."</em></p>
</blockquote>
<p><em>The gap was systemic, not session-specific.</em> Esa frase es la lección operativa del Issue. No fue un agente distraído un día; era el framework el que no le hablaba al agente sobre Charters en ningún lugar donde el agente miraba.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="6-lo-que-aprendí-sobre-visibilidad-estructural">6. Lo que aprendí sobre visibilidad estructural<a href="https://straymark.dev/es/blog/charters-invisible-to-agents#6-lo-que-aprend%C3%AD-sobre-visibilidad-estructural" class="hash-link" aria-label="Enlace directo al 6. Lo que aprendí sobre visibilidad estructural" title="Enlace directo al 6. Lo que aprendí sobre visibilidad estructural" translate="no">​</a></h2>
<p>La lección, escrita en prosa y no en tabla:</p>
<p>Crear un artefacto en un framework no es lo mismo que hacerlo visible para los agentes que trabajan en repos del framework. Son dos pasos. El primero — esquema, comando, template, ejemplos — es el paso visible: queda en el CHANGELOG, sale en el release, se ve en el <code>git log</code>. El segundo — anclar el artefacto en cada superficie por donde el agente entra al repo — es invisible: nada del segundo paso aparece como <em>feature</em> en sí; son referencias cruzadas, líneas en checklists, items en outputs, secciones en docs. Pero el segundo paso es el que decide si el primero existe para el agente.</p>
<p>El framework gobierna agentes que leen el repo desde fuera de la sesión donde se creó el artefacto. Cada agente que entra al repo construye su modelo mental desde cero, leyendo los documentos canónicos, las skills disponibles, los outputs de status. Si el artefacto no está nombrado ahí, no existe en su modelo. Y un modelo sin el artefacto no propone usarlo, no audita su ausencia, no señala disonancias relacionadas. La capacidad técnica del agente es irrelevante si la superficie del repo no le da el sustantivo correcto al entrar.</p>
<p>Eso es lo que ahora llamo, internamente, <em>visibilidad estructural</em>. No es una propiedad del agente. Es una propiedad del repo, y por extensión, una responsabilidad del framework: cada vez que cristaliza un concepto nuevo, tiene que multiplicar las superficies donde ese concepto se nombra. Una sola superficie — el schema, el comando, el template — no alcanza. Son nueve, mínimo, y son las nueve del Issue #113.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="7-cierre">7. Cierre<a href="https://straymark.dev/es/blog/charters-invisible-to-agents#7-cierre" class="hash-link" aria-label="Enlace directo al 7. Cierre" title="Enlace directo al 7. Cierre" translate="no">​</a></h2>
<p>Lo que aprendí del proceso, en cuatro tesis:</p>
<ol>
<li class="">
<p><strong>Existir como artefacto no es lo mismo que ser visible para el agente.</strong> Charters tenían schema, comando, template, ejemplos — y aun así eran invisibles. La diferencia entre los dos estados son las nueve superficies del Issue #113.</p>
</li>
<li class="">
<p><strong>Seis horas vs. cinco minutos.</strong> Un agente capaz puede pasar horas sin detectar lo que, una vez nombrado, le toma minutos integrar. La asimetría no diagnostica al agente; diagnostica al repo.</p>
</li>
<li class="">
<p><strong>La visibilidad estructural es responsabilidad del framework.</strong> Cuando cristaliza un concepto, no termina en el comando que lo crea. Termina cuando el concepto está nombrado en cada superficie donde el agente construye su modelo del repo: documento canónico, directiva, skill, status, template, puente con otros frameworks.</p>
</li>
<li class="">
<p><strong>Sin visibilidad estructural no hay observación emergente.</strong> Las propiedades que después hicieron posible que un agente señalara disonancias entre fuentes — vínculos formales + permiso cultural — necesitan, como precondición, que los artefactos sean visibles desde el primer momento del onboarding. El Issue #113 documenta qué pasa cuando esa precondición falta.</p>
</li>
</ol>
<p>Sigue, en el siguiente post, un episodio adyacente al de este: <em>el rebranding a StrayMark</em> (<code>H-08</code>). El Issue #113 se resolvió en el mismo arco temporal que el rename de DevTrail a StrayMark, y los dos comparten algo que vale la pena nombrar — la responsabilidad de que un framework declare con claridad su identidad, hacia sus agentes y hacia sus adopters.</p>
<hr>
<p><em>Anclas: <a href="https://github.com/StrangeDaysTech/straymark/issues/113" target="_blank" rel="noopener noreferrer" class="">Issue #113</a> (abierto 2026-05-07). <a href="https://github.com/StrangeDaysTech/straymark/pull/122" target="_blank" rel="noopener noreferrer" class="">PR #122</a> — <code>fw-4.12.0</code> (fusionado 2026-05-09). Documento generado por el PR: <a href="https://github.com/StrangeDaysTech/straymark/blob/main/dist/.straymark/00-governance/SPECKIT-CHARTER-BRIDGE.md" target="_blank" rel="noopener noreferrer" class=""><code>SPECKIT-CHARTER-BRIDGE.md</code></a>.</em></p>
<p><em>Este documento fue elaborado con asistencia de herramientas de IA generativa (Claude 4.7); toda la responsabilidad del contenido recae en el autor humano.</em></p>]]></content:encoded>
            <category>straymark</category>
            <category>charters</category>
            <category>agentes</category>
            <category>observabilidad</category>
            <category>governance</category>
        </item>
        <item>
            <title><![CDATA[El rebrand a StrayMark]]></title>
            <link>https://straymark.dev/es/blog/the-rebrand-to-straymark</link>
            <guid>https://straymark.dev/es/blog/the-rebrand-to-straymark</guid>
            <pubDate>Sat, 09 May 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[El cuarto rename, esta vez con ADR público y arco disciplinado]]></description>
            <content:encoded><![CDATA[<p><em>El cuarto rename, a diferencia de los tres primeros, no buscaba el concepto — vino de una investigación de conflicto de marca. Ocho días, un ADR, cinco PRs en cuarenta y tres minutos. El primer rebrand disciplinado del proyecto, y lo que "in scope / out of scope" significó al aplicarlo sobre su propio pasado.</em></p>
<!-- -->
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="1-el-rename-que-no-buscaba-el-concepto">1. El rename que no buscaba el concepto<a href="https://straymark.dev/es/blog/the-rebrand-to-straymark#1-el-rename-que-no-buscaba-el-concepto" class="hash-link" aria-label="Enlace directo al 1. El rename que no buscaba el concepto" title="Enlace directo al 1. El rename que no buscaba el concepto" translate="no">​</a></h2>
<p>El ADR <code>2026-05-08-001</code> se abre con una frase que, para cualquiera que haya leído el Post 2 de este blog, suena ajena:</p>
<blockquote>
<p><em>"The decision is motivated by legal certainty over the trademark rather than by product strategy or user feedback."</em></p>
</blockquote>
<p>Los tres renames de enero (Chronicle → Monimen → DevTrail) fueron búsqueda apurada del concepto. Cada uno ratificaba una intuición distinta sobre qué era el producto. Ninguno tenía ADR; los commit messages eran toda la justificación documental que existió.</p>
<p>El cuarto rename, el de mayo, es de otra naturaleza. No nace de buscar al concepto. Nace de una investigación de conflicto de <em>trademark</em> — comisionada vía sesión de Claude.ai a inicios de mayo — que arrojó <em>"legal uncertainty about trademark ownership as the project gained adopters"</em>. En enero el proyecto tenía cero adopters y los renames podían improvisarse. En mayo el proyecto tenía un adoptante (Sentinel), 286 descargas del <em>crate</em>, dos issues abiertos, y un manifesto público que prometía gobernanza estructurada. El umbral para improvisar otro rebrand ya había sido cruzado.</p>
<p>Este post cubre tres cosas: la decisión disciplinada que se tomó el 8 de mayo, el arco operativo de cinco PRs en cuarenta y tres minutos del día siguiente, y los residuos que aparecieron dos días después. Y, por dentro, una distinción más sutil: cuándo un rebrand es solo de superficie y cuándo, sin proponérselo del todo, cambia también la identidad.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="2-el-primer-rename-disciplinado">2. El primer rename disciplinado<a href="https://straymark.dev/es/blog/the-rebrand-to-straymark#2-el-primer-rename-disciplinado" class="hash-link" aria-label="Enlace directo al 2. El primer rename disciplinado" title="Enlace directo al 2. El primer rename disciplinado" translate="no">​</a></h2>
<p>Lo nuevo del 8 de mayo es la forma. Esta vez había:</p>
<ul>
<li class=""><strong>Una investigación previa.</strong> No se decidió rebrand y luego se justificó; primero hubo un conflicto detectado y luego, en consecuencia, la decisión.</li>
<li class=""><strong>Un ADR público.</strong> Tres alternativas consideradas explícitamente (mantener "DevTrail" y aceptar el riesgo; branding híbrido legacy + nuevo en paralelo; reset a v0.1.0 bajo StrayMark como "proyecto nuevo"). Las tres descartadas con argumento literal.</li>
<li class=""><strong>Un cálculo temporal.</strong> El propio ADR enmarca el costo así: <em>"The rename window narrows over time — every new adopter increases the cost of changing later... The legal risk dominates. Acting now, with one self-owned adopter, is materially cheaper than acting later under pressure."</em></li>
</ul>
<p>La razón por la que el cálculo importa es estructural. Si el rebrand hubiera esperado dos meses más — hasta que apareciera el segundo adopter, o el tercero — el costo de migración se habría multiplicado. Cada repo adopter habría tenido que ejecutar el <code>mv .devtrail .straymark</code>, actualizar sus <code>CLAUDE.md</code>/<code>AGENT.md</code>, regenerar sus pipelines. Con un solo adopter (el propio operador), el costo era contenido y revertible. Lo que el ADR llama <em>"acting now is materially cheaper"</em> es exactamente eso: el rebrand fue una operación de minimización de deuda futura, no una decisión de marketing.</p>
<p>Hay un eco no buscado con el Post 2. Aquel cerró con la frase <em>"probablemente no vuelva a haber rebranding"</em>. Este post, escrito desde mayo, sabe que sí lo hubo. La diferencia entre prometer y ratificar es que el cuarto rename, a diferencia de los tres primeros, fue forzado por circunstancias externas que ningún operador puede prever — un conflicto de trademark — y se enfrentó con la disciplina que enero no tenía.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="3-in-scope-out-of-scope--la-pieza-maestra-del-adr">3. <em>In scope</em>, <em>out of scope</em> — la pieza maestra del ADR<a href="https://straymark.dev/es/blog/the-rebrand-to-straymark#3-in-scope-out-of-scope--la-pieza-maestra-del-adr" class="hash-link" aria-label="Enlace directo al 3-in-scope-out-of-scope--la-pieza-maestra-del-adr" title="Enlace directo al 3-in-scope-out-of-scope--la-pieza-maestra-del-adr" translate="no">​</a></h2>
<p>La sección del ADR que da forma al resto del post es la que distingue qué se renombra y qué se preserva. Citada literal:</p>
<blockquote>
<p><em>"In scope (the 'live state' of the project): all identifiers in source code, Cargo metadata, source-of-truth path, 30 skill/workflow files, public documentation, CI workflows, GitHub repository name."</em></p>
</blockquote>
<blockquote>
<p><em>"Out of scope (immutable history, preserved verbatim): all commits, commit messages, and git history; all tags published before this ADR; all release titles and bodies of releases published before; all prior CHANGELOG.md sections."</em></p>
</blockquote>
<p>Esa distinción es la armadura del rebrand. Lo <em>live</em> — paths, comandos, URLs, assets de release, README — se renombra de un golpe. Lo <em>historic</em> — git log, tags <code>devtrail-cli@3.10.0</code>, sections previas del CHANGELOG, issues cerrados — se preserva literal. El proyecto no se reescribe hacia atrás.</p>
<p>Es la misma disciplina archivística que el Post 3 documentó para el rename Plan → Charter, ahora aplicada al rebrand operativo del framework completo. Lo expreso en una tabla porque ayuda a verlo:</p>




























































<table><thead><tr><th>Capa</th><th>Se renombra</th><th>Se preserva</th></tr></thead><tbody><tr><td>Paths del filesystem</td><td><code>.devtrail/</code> → <code>.straymark/</code></td><td>—</td></tr><tr><td>Source Rust</td><td><code>devtrail-cli</code> → <code>straymark-cli</code></td><td>—</td></tr><tr><td>Skills/workflows</td><td>30 archivos <code>devtrail-*</code> → <code>straymark-*</code></td><td>—</td></tr><tr><td>Docs públicas</td><td>README, CLAUDE.md, ADOPTION-GUIDE</td><td>—</td></tr><tr><td>CI/CD</td><td>nombres de assets, paths de binarios</td><td>Prefijos de tag (<code>fw-</code>, <code>cli-</code>) sin tocar</td></tr><tr><td>Repositorio GitHub</td><td><code>StrangeDaysTech/devtrail</code> → <code>StrangeDaysTech/straymark</code></td><td>—</td></tr><tr><td>CHANGELOG</td><td>Nueva entrada <code>fw-4.11.0</code> arriba</td><td>Secciones previas literal</td></tr><tr><td>Tags publicados</td><td>—</td><td><code>fw-4.10.0</code>, <code>cli-3.10.0</code>, etc. preservados</td></tr><tr><td>Git log entero</td><td>—</td><td>Mensajes con "DevTrail" intactos</td></tr><tr><td><em>Crate</em> legacy</td><td>—</td><td><code>devtrail-cli@3.10.0</code> en crates.io, no <em>yanked</em></td></tr></tbody></table>
<p>La continuidad de versiones es la prueba más visible. El siguiente release no fue <code>0.1.0</code> ni <code>1.0.0</code>; fue <code>fw-4.11.0</code> y <code>cli-3.11.0</code>. La numeración declara, sin metáfora, que el proyecto es el mismo proyecto.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="4-cinco-prs-cuarenta-y-tres-minutos">4. Cinco PRs, cuarenta y tres minutos<a href="https://straymark.dev/es/blog/the-rebrand-to-straymark#4-cinco-prs-cuarenta-y-tres-minutos" class="hash-link" aria-label="Enlace directo al 4. Cinco PRs, cuarenta y tres minutos" title="Enlace directo al 4. Cinco PRs, cuarenta y tres minutos" translate="no">​</a></h2>
<p>El 9 de mayo, entre las 06:05 y las 06:48 UTC, se fusionaron cinco PRs en cadena:</p>



































<table><thead><tr><th>PR</th><th>Hora UTC</th><th>Qué hizo</th></tr></thead><tbody><tr><td><a href="https://github.com/StrangeDaysTech/straymark/pull/114" target="_blank" rel="noopener noreferrer" class="">#114</a></td><td>06:05</td><td>Merge del ADR mismo. Cero cambios de código — primero se fija la decisión.</td></tr><tr><td><a href="https://github.com/StrangeDaysTech/straymark/pull/115" target="_blank" rel="noopener noreferrer" class="">#115</a></td><td>06:42</td><td>174 <em>renames</em> + 74 modificaciones. Source Rust (38 archivos), tests (18), <code>dist/.devtrail/</code> → <code>dist/.straymark/</code> (122 archivos vía <code>git mv</code>), 30 skills × 3 plataformas.</td></tr><tr><td><a href="https://github.com/StrangeDaysTech/straymark/pull/116" target="_blank" rel="noopener noreferrer" class="">#116</a></td><td>06:44</td><td>Docs públicas en tres idiomas (EN/ES/zh-CN). Preámbulo del CHANGELOG actualizado: <em>"StrayMark (formerly DevTrail; rebranded 2026-05-08)"</em>.</td></tr><tr><td><a href="https://github.com/StrangeDaysTech/straymark/pull/117" target="_blank" rel="noopener noreferrer" class="">#117</a></td><td>06:45</td><td>Workflows de release. Nombres de assets (<code>straymark-cli-*</code>), títulos de release. Prefijos de tag intactos.</td></tr><tr><td><a href="https://github.com/StrangeDaysTech/straymark/pull/118" target="_blank" rel="noopener noreferrer" class="">#118</a></td><td>06:48</td><td>Bump <code>fw-4.11.0</code> / <code>cli-3.11.0</code>. Nueva sección del CHANGELOG.</td></tr></tbody></table>
<p>El orden es deliberado y va de afuera hacia adentro: primero la ley (ADR), después el código interno, después lo que ven los adopters (docs), después la distribución (CI), finalmente el hecho consumado (release). Esta secuencia tiene una lectura archivística: cuando alguien dentro de seis meses revise <code>git log</code> en orden cronológico, primero verá la decisión, después la implementación. La causalidad queda en el repo.</p>
<p>Vale la pena nombrar una pieza del arco que rompió el plan original. El ADR había contemplado nueve PRs distintos (uno por capa lógica). En la práctica, los tests del CLI dependían de paths <em>hardcoded</em> — <code>include_str!("../../dist/.devtrail/...")</code> — y romper el path sin actualizar los tests al mismo tiempo dejaba CI en rojo. El plan se compactó a cinco porque las capas estaban acopladas técnicamente, no porque la disciplina conceptual fallara. La nota del PR #115 lo registra sin atenuar: <em>"The consolidation was forced by tight coupling: tests use <code>include_str!</code> on <code>dist/.devtrail/</code> paths."</em></p>
<p>Cuarenta y tres minutos para un rebrand que tocó alrededor de doscientos sesenta archivos. La cadencia solo es posible porque el ADR había cerrado todas las decisiones antes de tocar código. El principio #6 del framework — <em>"cuando la propuesta es bien escrita, la implementación es ejecución, no diseño"</em> — encontró otro caso de validación, parecido al del audit cycle externo del Post 4.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="5-por-qué-straymark-sí-cambia-algo-más-que-el-nombre">5. Por qué StrayMark sí cambia algo más que el nombre<a href="https://straymark.dev/es/blog/the-rebrand-to-straymark#5-por-qu%C3%A9-straymark-s%C3%AD-cambia-algo-m%C3%A1s-que-el-nombre" class="hash-link" aria-label="Enlace directo al 5. Por qué StrayMark sí cambia algo más que el nombre" title="Enlace directo al 5. Por qué StrayMark sí cambia algo más que el nombre" translate="no">​</a></h2>
<p>Hasta aquí el ADR es claro: el rebrand es de superficie, la identidad conceptual se preserva. Pero hay un matiz que vale la pena nombrar.</p>
<p>El PR <a href="https://github.com/StrangeDaysTech/straymark/pull/120" target="_blank" rel="noopener noreferrer" class="">#120</a> — fusionado horas después del arco principal, el mismo 9 de mayo — añadió al README la sección <em>"Why StrayMark?"</em>. No es código; es un manifesto. Y dice cosas que ningún documento previo del proyecto había articulado:</p>
<blockquote>
<p><em>"Code is just the fossil trace of a mental battle. Real engineering happens in the chaos of decisions, calculated risks, and the paths you chose not to take. Traditionally, all that human trail is discarded as stray marks (accidental smudges) in a project's history. At Strange Days Tech, we believe those marks are the signal, not the noise."</em></p>
</blockquote>
<p>La elección del nombre, vista desde el manifesto, no es arbitraria. Las <em>stray marks</em> — las marcas erráticas, las trazas accidentales que la mayoría de proyectos descartan — son exactamente lo que el framework arrastra a primer plano: AIDECs, AILOGs, TDEs, Charters. Lo que en cualquier proyecto convencional sería ruido descartable, en este proyecto es la materia prima de la auditoría. El nombre encarna la tesis del producto en una forma que <em>DevTrail</em> nunca lo hizo. <em>DevTrail</em> era un recorrido neutro; <em>StrayMark</em> es una afirmación.</p>
<p>El manifesto cierra con tres líneas que después se volvieron lo que un editor llamaría <em>tagline</em> operativo:</p>
<blockquote>
<p><em>"Capture the noise. Weave the signal. Humanize the machine."</em></p>
</blockquote>
<p>Aquí está la pequeña tensión interesante del rebrand. El ADR dice que solo cambió la superficie; el manifesto del mismo día sugiere que también se articuló — quizás por primera vez con claridad — la identidad. No es contradicción: el momento del rebrand operativo fue aprovechado para escribir lo que ya estaba en el proyecto pero no se había nombrado todavía. La identidad no cambió. Se hizo legible.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="6-lo-que-quedó-pendiente">6. Lo que quedó pendiente<a href="https://straymark.dev/es/blog/the-rebrand-to-straymark#6-lo-que-qued%C3%B3-pendiente" class="hash-link" aria-label="Enlace directo al 6. Lo que quedó pendiente" title="Enlace directo al 6. Lo que quedó pendiente" translate="no">​</a></h2>
<p>Aun con ADR público y arco disciplinado, <em>"completo"</em> sigue siendo aproximación.</p>
<p>Dos días después del rebrand, mientras Sentinel preparaba su siguiente ciclo de auditoría externa, el agente señaló tres clases de residuos. La cronología — captura honesta en <code>CHANGELOG.md</code> como erratas inline — vale la pena dejarla a la vista:</p>
<ul>
<li class=""><strong>PR <a href="https://github.com/StrangeDaysTech/straymark/pull/137" target="_blank" rel="noopener noreferrer" class="">#137</a></strong> (11 may, 22:55) — <em>Skill directories órfanos</em>. El rebrand reescribió el campo <code>name:</code> dentro de cada <code>SKILL.md</code>, pero no renombró los directorios de las tres plataformas (<code>.gemini/skills/devtrail-*</code>, <code>.claude/skills/devtrail-*</code>, <code>.agent/workflows/devtrail-*.md</code>). Treinta artefactos órfanos: nombre nuevo, ruta vieja. Gemini CLI lo reportó como diez warnings de conflicto al arrancar.</li>
<li class=""><strong>PR <a href="https://github.com/StrangeDaysTech/straymark/pull/138" target="_blank" rel="noopener noreferrer" class="">#138</a></strong> (11 may, 23:32) — <em>Charter paths legacy</em>. Tres artefactos del framework seguían referenciando <code>docs/charters/</code> después de que <code>fw-4.12.0</code> migró el path canónico a <code>.straymark/charters/</code>. Lo más grave: el hook <code>pre-pr.sh</code> estaba gated en <code>[ ! -d docs/charters ]</code>, lo cual hacía <em>exit 0</em> silencioso para cualquier adopter post-4.12.0. El drift check llevaba siete meses instalado pero no-op.</li>
<li class=""><strong>PR <a href="https://github.com/StrangeDaysTech/straymark/pull/139" target="_blank" rel="noopener noreferrer" class="">#139</a></strong> (12 may, 12:02) — <em>Instaladores rotos</em>. <code>install.sh</code> e <code>install.ps1</code> aún apuntaban a <code>REPO=StrangeDaysTech/devtrail</code>, <code>BINARY=devtrail</code>, asset name <code>devtrail-cli-v*</code>. El README — ya rebranded — apuntaba a la nueva URL. Resultado: cualquier usuario que copiara el comando del README desde el 9 de mayo recibía un 404 de GitHub al ejecutar el instalador. <em>El producto estuvo roto en producción durante setenta y dos horas.</em></li>
<li class=""><strong>PR <a href="https://github.com/StrangeDaysTech/straymark/pull/140" target="_blank" rel="noopener noreferrer" class="">#140</a></strong> (12 may, 16:49) — <em>Micro-residuo</em>. La línea uno de <code>.gitignore</code> decía aún <code># DevTrail - .gitignore</code>. Más una entrada nueva para <code>Aparador/</code> en patterns internos.</li>
</ul>
<p>La lección no es que la disciplina fue insuficiente. Es que la disciplina <em>no previene</em> residuos — los hace encontrables, documentables, y reparables en errata inline pública. Los tres primeros renames (enero) probablemente tuvieron residuos equivalentes; nunca los catalogamos porque no había hábito documental. El cuarto rebrand los catalogó. Es el primer rebrand del proyecto que admite, en el repo público y en el CHANGELOG mismo, que el operario no atrapó todo a la primera.</p>
<p>El detalle más incómodo — los instaladores rotos por setenta y dos horas — es el que más me importa registrar. Si en lugar de un adopter solo (el operador) hubiera habido un equipo, esa ventana habría afectado a usuarios reales. Acting now, with one self-owned adopter, was materially cheaper, says the ADR. Eso es exactamente lo que esa frase compraba: el derecho a equivocarse durante setenta y dos horas sin lastimar a nadie.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="7-cierre">7. Cierre<a href="https://straymark.dev/es/blog/the-rebrand-to-straymark#7-cierre" class="hash-link" aria-label="Enlace directo al 7. Cierre" title="Enlace directo al 7. Cierre" translate="no">​</a></h2>
<p>Lo que aprendí del proceso, en cuatro tesis:</p>
<ol>
<li class="">
<p><strong>No todos los renames son del mismo tipo.</strong> Los tres de enero buscaban al concepto; el de mayo defendía al proyecto contra deuda futura legal. Solo el de mayo podía hacerse con ADR público, porque solo el de mayo nacía de evidencia externa y no de intuición interna.</p>
</li>
<li class="">
<p><strong>La distinción superficie vs. identidad pertenece al documento, no a la retórica.</strong> El ADR mismo declara qué se renombra y qué se preserva. Esa lista — paths sí, git log no; release titles sí, tags previos no — es la armadura del rebrand. Sin esa lista explícita, <em>"rebrand"</em> significa cualquier cosa.</p>
</li>
<li class="">
<p><strong>La identidad puede hacerse legible aunque no cambie.</strong> El manifesto <em>"Why StrayMark?"</em> no inventó lo que el proyecto era; lo articuló por primera vez con claridad. El rebrand operativo fue aprovechado para escribir lo que ya estaba en el código pero no había salido al README. La identidad no se reescribió, se publicó.</p>
</li>
<li class="">
<p><strong>La disciplina no previene residuos; los hace encontrables.</strong> Cuatro PRs <em>errata</em> dos días después no son falla del rebrand; son evidencia de que el rebrand fue lo suficientemente honesto como para admitir qué se le escapó. Los tres renames de enero probablemente tuvieron equivalentes; nunca aparecieron documentados.</p>
</li>
</ol>
<p>Sigue, en el siguiente post, un episodio que conecta directamente con el último punto: <em>TDE como mecanismo para nombrar deuda transversal</em> (<code>H-09</code>). El primer caso real que el framework usó para articular cómo evidenciar la deuda — y que dejó una lección dura sobre stacked-PRs que merece su propio párrafo cuando llegue ahí.</p>
<hr>
<p><em>Anclas: ADR <a href="https://github.com/StrangeDaysTech/straymark/blob/main/docs/decisions/ADR-2026-05-08-rebranding-straymark.md" target="_blank" rel="noopener noreferrer" class=""><code>2026-05-08-001</code></a>. Arco nuclear: PRs <a href="https://github.com/StrangeDaysTech/straymark/pull/114" target="_blank" rel="noopener noreferrer" class="">#114</a> · <a href="https://github.com/StrangeDaysTech/straymark/pull/115" target="_blank" rel="noopener noreferrer" class="">#115</a> · <a href="https://github.com/StrangeDaysTech/straymark/pull/116" target="_blank" rel="noopener noreferrer" class="">#116</a> · <a href="https://github.com/StrangeDaysTech/straymark/pull/117" target="_blank" rel="noopener noreferrer" class="">#117</a> · <a href="https://github.com/StrangeDaysTech/straymark/pull/118" target="_blank" rel="noopener noreferrer" class="">#118</a>. Manifesto: PR <a href="https://github.com/StrangeDaysTech/straymark/pull/120" target="_blank" rel="noopener noreferrer" class="">#120</a>. Residuos: PRs <a href="https://github.com/StrangeDaysTech/straymark/pull/137" target="_blank" rel="noopener noreferrer" class="">#137</a> · <a href="https://github.com/StrangeDaysTech/straymark/pull/138" target="_blank" rel="noopener noreferrer" class="">#138</a> · <a href="https://github.com/StrangeDaysTech/straymark/pull/139" target="_blank" rel="noopener noreferrer" class="">#139</a> · <a href="https://github.com/StrangeDaysTech/straymark/pull/140" target="_blank" rel="noopener noreferrer" class="">#140</a>. Release: <code>fw-4.11.0</code> / <code>cli-3.11.0</code>.</em></p>
<p><em>Este documento fue elaborado con asistencia de herramientas de IA generativa (Claude 4.7); toda la responsabilidad del contenido recae en el autor humano.</em></p>]]></content:encoded>
            <category>straymark</category>
            <category>rebranding</category>
            <category>governance</category>
            <category>identidad</category>
        </item>
        <item>
            <title><![CDATA[Charters como entidad de primera clase, y el audit cycle externo]]></title>
            <link>https://straymark.dev/es/blog/charters-and-the-external-audit-cycle</link>
            <guid>https://straymark.dev/es/blog/charters-and-the-external-audit-cycle</guid>
            <pubDate>Wed, 06 May 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[De ritual manual en Sentinel a comando CLI canonizado]]></description>
            <content:encoded><![CDATA[<p><em>Cuarenta minutos de copy-paste por Charter encima de dos horas de trabajo. La disciplina funcionaba; el ritual se estaba volviendo el problema. Cómo el Charter pasó a ser entidad de primera clase del CLI, y la decisión arquitectónica que dejó la orquestación de auditoría al framework y la evaluación del prompt a cualquier otro.</em></p>
<!-- -->
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="1-cuando-la-disciplina-amenaza-con-volverse-ceremonia">1. Cuando la disciplina amenaza con volverse ceremonia<a href="https://straymark.dev/es/blog/charters-and-the-external-audit-cycle#1-cuando-la-disciplina-amenaza-con-volverse-ceremonia" class="hash-link" aria-label="Enlace directo al 1. Cuando la disciplina amenaza con volverse ceremonia" title="Enlace directo al 1. Cuando la disciplina amenaza con volverse ceremonia" translate="no">​</a></h2>
<p>A finales de abril, Sentinel cerró su cuarto Charter del mes con una sensación que, escrita, suena un poco patética: la auditoría externa funcionaba — Copilot 9.25, Gemini 9.5, el drift script con cero falsos positivos — pero cada cierre me hacía abrir tres archivos a mano, copiar tres prompts a tres ventanas distintas, esperar respuestas, copiar tres YAMLs de calibración de vuelta al archivo de telemetría, y verificar a ojo que los hashes coincidían. Cuarenta minutos de copy-paste por Charter, sobre un trabajo que tomaba dos horas. La disciplina estaba funcionando; el ritual estaba volviéndose un problema.</p>
<p>La propuesta <code>audit-skills-design.md</code>, escrita el 3 de mayo, lo nombró sin atenuar:</p>
<blockquote>
<p><em>"Si en cada cierre el operador tuviera que mover datos manualmente entre archivos, el throughput colapsaría y la disciplina dejaría de ser fricción virtuosa para volverse ceremonia. Lo que se pueda automatizar de forma reversible debe automatizarse; los documentos quedan para auditoría humana ex-post."</em></p>
</blockquote>
<p>Este post cubre tres días — del 2 al 6 de mayo de 2026 — en los que dos arcos paralelos terminaron a la vez. Uno: el Charter dejó de ser práctica artesanal y se volvió entidad de primera clase del CLI. Dos: el audit cycle externo dejó de ser ritual manual con prompts ad-hoc y se volvió comando canónico (con una decisión arquitectónica contraintuitiva detrás que merece su propio párrafo).</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="2-lo-que-sentinel-ya-hacía-y-lo-que-straymark-no-tenía">2. Lo que Sentinel ya hacía, y lo que StrayMark no tenía<a href="https://straymark.dev/es/blog/charters-and-the-external-audit-cycle#2-lo-que-sentinel-ya-hac%C3%ADa-y-lo-que-straymark-no-ten%C3%ADa" class="hash-link" aria-label="Enlace directo al 2. Lo que Sentinel ya hacía, y lo que StrayMark no tenía" title="Enlace directo al 2. Lo que Sentinel ya hacía, y lo que StrayMark no tenía" translate="no">​</a></h2>
<p>La propuesta del 3 de mayo lo dice con una frase que se queda corta de elegante pero precisa exactamente lo que estaba pasando:</p>
<blockquote>
<p><em>"Sentinel tiene los skills, StrayMark no."</em></p>
</blockquote>
<p>Lo que Sentinel tenía: <code>sentinel/.claude/skills/plan-audit/</code> y <code>plan-audit-review/</code> — skills locales que generaban un prompt, calibraban la respuesta al regreso, y la fusionaban en la telemetría. Funcionaban. Llevaban seis ciclos validándose. Pero estaban acoplados a paths Sentinel-específicos (<code>docs/plans/</code>, <code>internal/modules/</code>, <code>go vet</code>) y al vocabulario <em>"Plan"</em>, que ya había sido renombrado a Charter una semana antes.</p>
<p>Lo que StrayMark no tenía: nada equivalente. El framework hasta abril era documentación + skills + un CLI con <code>init</code>, <code>update</code>, <code>remove</code>. La unidad que en Sentinel se llamaba <em>Plan</em> — la unidad acotada, declarada <em>ex-ante</em>, auditada <em>ex-post</em> — no existía como artefacto del CLI. Existía como práctica.</p>
<p>El arco de fw-4.4.0 (2 de mayo) y de fw-4.7 → 4.9 (3-5 de mayo) consiste, casi al pie de la letra, en portar lo que Sentinel hacía a mano hacia comandos genéricos que cualquier adoptante del framework pueda invocar. La tabla de migración, copiada del <code>cli-roadmap.md</code>, es honesta sobre el origen:</p>





























<table><thead><tr><th>Artefacto Sentinel <em>(abril 2026)</em></th><th>Equivalente StrayMark <em>(mayo 2026)</em></th></tr></thead><tbody><tr><td><code>TEMPLATE.md</code> (v3) en <code>docs/plans/</code></td><td><code>dist/.straymark/templates/charter-template.md</code></td></tr><tr><td><code>scripts/check-plan-drift.sh</code> (145 líneas bash)</td><td><code>straymark charter drift</code> (subcomando Rust)</td></tr><tr><td>Skill local <code>plan-audit</code></td><td>Skill genérica <code>straymark-audit-prepare</code></td></tr><tr><td>Reportes duales en <code>audit/plans/05,06/{copilot,gemini,claude}.md</code></td><td>Output canónico de <code>straymark charter audit</code></td></tr><tr><td>YAML de telemetría a mano</td><td><code>dist/.straymark/schemas/charter-telemetry.schema.v0.json</code></td></tr></tbody></table>
<p>El CHANGELOG de fw-4.4.0 lo enmarca sin metáfora: <em>"Crystallizes the Charter pattern — bounded, auditable units of work declared ex-ante and validated ex-post — that emerged from the 6-cycle Sentinel /plan-audit experiment."</em> La cristalización es el punto. Lo que en abril era costumbre con script bash, en mayo es comando con schema validable.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="3-qué-pasa-cuando-algo-se-vuelve-entidad-de-primera-clase">3. Qué pasa cuando algo se vuelve "entidad de primera clase"<a href="https://straymark.dev/es/blog/charters-and-the-external-audit-cycle#3-qu%C3%A9-pasa-cuando-algo-se-vuelve-entidad-de-primera-clase" class="hash-link" aria-label="Enlace directo al 3. Qué pasa cuando algo se vuelve &quot;entidad de primera clase&quot;" title="Enlace directo al 3. Qué pasa cuando algo se vuelve &quot;entidad de primera clase&quot;" translate="no">​</a></h2>
<p>PR #65 (fw-4.4.0 / cli-3.6.0, 2 de mayo) hace tres cosas concretas:</p>
<ul>
<li class="">Crea el comando <code>straymark charter new</code>. Auto-incrementa el número (<code>NN-slug.md</code>), pre-popula el origen (<code>originating_ailogs</code> si nace de un AILOG previo; <code>originating_spec</code> si nace de un SpecKit <code>plan.md</code>), y soporta el flag <code>--type X|S|M|L</code> para fijar la escala desde el primer momento.</li>
<li class="">Introduce <code>charter-template.md</code> portado del <code>TEMPLATE.md</code> v3 de Sentinel. Lleva embebidas las seis convenciones que el experimento de abril fue cristalizando ciclo a ciclo: separación Local/Production checks, esfuerzo en tiempo (no en story points), sub-secciones estructuradas, documentación de riesgos <code>R&lt;N&gt;</code>, cierre con reconciliación post-merge vía AILOG, y auto-checklist drift.</li>
<li class="">Publica <code>dist/.straymark/schemas/charter.schema.v0.json</code> — el schema marcado como <code>v0</code> deliberadamente, no <code>v1</code>, porque el principio #12 del framework dice que ningún schema cristaliza sin un segundo dominio que lo valide. Sentinel es un dominio. Falta el segundo.</li>
</ul>
<p>PR #68 (3 de mayo) hace algo que parece pequeño pero importa: el <em>atomic Charter closure pattern</em>, format v4. En Sentinel, el paso <em>"actualizar el Plan-doc post-merge si el AILOG documenta divergencias"</em> existía como nota en el TEMPLATE pero no tenía gatillo sistemático. En la práctica, eso significaba que cuando había diferencia entre lo declarado y lo entregado, el operador (yo) confiaba en la memoria para reconciliar el documento — y la memoria fallaba. El drift quedaba en el repo días, a veces semanas, hasta que el siguiente ciclo lo descubría. Format v4 vuelve la reconciliación un paso obligatorio del cierre, no una nota al margen.</p>
<p>PR #69 (mismo día) cierra un detalle de fricción: la numeración manual. Antes había que decidir si el siguiente Charter era 11 o 12; ahora <code>straymark charter new</code> lee el directorio y propone el siguiente número. UX puro. Pero es la clase de fricción que, sumada sobre veinte Charters, decide si el framework se usa o se abandona.</p>
<p>Los tres PRs salieron en el mismo <em>commit storm</em> de un domingo y un lunes. Esa cadencia es deliberada: una vez que el patrón se cristaliza, los detalles UX hay que cerrarlos <em>junto</em>, no en bumps separados que dejen al adoptante con una mitad del flujo.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="4-tres-releases-en-un-día">4. Tres releases en un día<a href="https://straymark.dev/es/blog/charters-and-the-external-audit-cycle#4-tres-releases-en-un-d%C3%ADa" class="hash-link" aria-label="Enlace directo al 4. Tres releases en un día" title="Enlace directo al 4. Tres releases en un día" translate="no">​</a></h2>
<p>Lo que vino después — fw-4.7.0, fw-4.8.0, fw-4.9.0 — son releases consecutivos del audit cycle externo. La propuesta <code>audit-skills-rollout.md</code> registra el ritmo sin disimular:</p>
<blockquote>
<p><em>"Fase 1 ejecutada en 1 día calendar (5 PRs secuenciales el 3 de mayo de 2026), substancialmente más rápido que la estimación de 1.5-2 semanas focused. El throughput se debe a que el diseño en <code>audit-skills-design.md</code> ya tenía las decisiones cristalizadas (D1/D2/D3) y la heurística arborist con graceful-degradation explícita — no hubo decisiones pendientes durante la implementación. Sirve como evidencia operativa adicional para principio #6 (cuando la propuesta es bien escrita, la implementación es ejecución, no diseño)."</em></p>
</blockquote>
<p>El audit cycle externo concreto consiste en tres comandos encadenados:</p>
<ol>
<li class=""><code>straymark charter audit prepare &lt;CHARTER-NN&gt;</code> — genera prompts canónicos para auditores externos a partir del Charter cerrado, su AILOG asociado, y el diff de archivos tocados. Output: tres archivos <code>.prompt.md</code> en <code>audit/&lt;CHARTER-NN&gt;/{copilot,gemini,claude}.prompt.md</code>.</li>
<li class=""><em>(El humano lleva esos prompts a su auditor de elección, recibe respuestas, las pega de vuelta.)</em></li>
<li class=""><code>straymark charter audit collect &lt;CHARTER-NN&gt;</code> — toma las respuestas, valida cada una contra el schema de auditoría, fusiona calibraciones en la telemetría del Charter, y produce un summary con la convergencia (o divergencia) entre auditores.</li>
</ol>
<p>Decisión D1 de la propuesta es la que sostiene todo lo demás:</p>
<blockquote>
<p><em>"Las skills delegan vía <code>Bash(straymark charter audit *)</code> a la implementación canónica. Plantillas viven solo en <code>dist/.straymark/audit-prompts/</code>. Cero drift posible entre skill y CLI."</em></p>
</blockquote>
<p>Hay solo un lugar donde los prompts viven, una sola implementación del flow, y las skills (Claude, Cursor) lo invocan vía Bash. Es un patrón humilde — el CLI es la fuente única — pero evita lo que en cualquier framework con dos surfaces (skill + CLI) termina siendo el problema crónico: que el skill y el CLI digan cosas distintas según quién los actualizó la última vez.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="5-por-qué-el-cli-orquesta-pero-no-invoca-apis">5. Por qué el CLI orquesta pero no invoca APIs<a href="https://straymark.dev/es/blog/charters-and-the-external-audit-cycle#5-por-qu%C3%A9-el-cli-orquesta-pero-no-invoca-apis" class="hash-link" aria-label="Enlace directo al 5. Por qué el CLI orquesta pero no invoca APIs" title="Enlace directo al 5. Por qué el CLI orquesta pero no invoca APIs" translate="no">​</a></h2>
<p>Esta es la decisión más rara de mayo, y la que más me costó tomar. Está documentada literal en <code>cli-roadmap.md</code> §0 como <em>"decisión arquitectónica A1"</em>:</p>
<blockquote>
<p><em>"A1 (Phase 3): orchestration-only, no HTTP API clients en v0. El roadmap §5.4 originalmente sugería 'soportar OpenAI/Google/Anthropic en v0' con manejo de API keys. La realidad implementada es que el CLI prepara prompts, valida outputs contra schema, e integra con telemetría — pero NO invoca APIs. El operador pega los prompts en su auditor de elección manualmente."</em></p>
</blockquote>
<p>El razonamiento, también literal:</p>
<blockquote>
<p><em>"Implementar 3 clientes HTTP es 1-2 semanas + mantenimiento perpetuo cuando cambian las APIs (premature para una v0 experimental); el patrón humano-en-el-loop coincide con <code>/plan-audit</code> de Sentinel; cumple principio #10 ('no es un LLM gateway'); cierra RFC #82 por diseño. Los HTTP clients se reabren en v1 cuando un adoptante real lo justifique con datos."</em></p>
</blockquote>
<p>Tres argumentos, cada uno con peso propio.</p>
<p><strong>El primero es pragmático</strong>. Tres clientes HTTP — OpenAI, Anthropic, Google — son entre una y dos semanas de implementación, más mantenimiento permanente cada vez que alguno de los tres cambia algo. Para un comando que en su forma manual ya estaba funcionando empíricamente en Sentinel, ese es un costo absurdo. Es ingeniería para resolver un problema que ningún adoptante había pedido resolver.</p>
<p><strong>El segundo es de continuidad</strong>. Lo que Sentinel validó en abril fue precisamente el patrón humano-en-el-loop: el operador pega el prompt en Copilot/Gemini/Claude <em>a mano</em>, lee la respuesta, la pega de vuelta. El experimento de los seis Planes que dio origen a este arco completo <em>nunca</em> invocó APIs. Si el CLI ahora invocara APIs por su cuenta, estaría sustituyendo el patrón validado con uno no validado, sin razón empírica.</p>
<p><strong>El tercero es de identidad</strong>. StrayMark no es un <em>LLM gateway</em>. El principio #10 del framework lo dice explícitamente. Hay docenas de productos que sí lo son — LangChain, LiteLLM, LiteLLM Proxy, OpenRouter, todos los wrappers — y son útiles para lo que hacen. StrayMark hace otra cosa: estructura la disciplina alrededor del trabajo que se hace <em>con</em> esos modelos, sea cual sea el modelo. Que el CLI invoque o no invoque APIs cambia lo que el framework es; mantenerlo <em>orchestration-only</em> mantiene la identidad limpia.</p>
<p>La parte que más me importa del párrafo: <em>"Los HTTP clients se reabren en v1 cuando un adoptante real lo justifique con datos."</em> La decisión no se cerró por dogma; se difirió por umbral de evidencia. Si en seis meses un adoptante demuestra que el flow humano-en-el-loop le rompe el throughput, los HTTP clients aterrizan. Hasta entonces, la fricción manual de los cuarenta segundos que toma pegar el prompt en otra ventana es trivial comparada con el costo de mantener tres SDKs vivos.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="6-lo-que-el-framework-decidió-no-automatizar">6. Lo que el framework decidió <em>no</em> automatizar<a href="https://straymark.dev/es/blog/charters-and-the-external-audit-cycle#6-lo-que-el-framework-decidi%C3%B3-no-automatizar" class="hash-link" aria-label="Enlace directo al 6-lo-que-el-framework-decidió-no-automatizar" title="Enlace directo al 6-lo-que-el-framework-decidió-no-automatizar" translate="no">​</a></h2>
<p>Vale la pena cerrar con la otra cara de la misma decisión. La propuesta <code>audit-skills-design.md</code> dice:</p>
<blockquote>
<p><em>"Lo que se pueda automatizar de forma reversible debe automatizarse; los documentos quedan para auditoría humana ex-post."</em></p>
</blockquote>
<p>La primera mitad explica los tres releases de mayo: prompts generados automáticamente, calibraciones fusionadas automáticamente, drift detectado automáticamente. La segunda mitad — <em>"los documentos quedan para auditoría humana ex-post"</em> — explica qué se decidió mantener manual a propósito.</p>
<p>Lo que el framework <em>no</em> automatiza:</p>
<ul>
<li class=""><strong>La lectura del AILOG por parte del operador antes de cerrar el Charter.</strong> El comando <code>straymark charter audit prepare</code> genera los prompts, pero el operador <em>tiene</em> que abrir el AILOG y leerlo. Si automatizáramos eso — un agente que lee, resume, decide — perderíamos el momento de juicio humano que justifica que el Charter exista.</li>
<li class=""><strong>La decisión de aceptar o rechazar la auditoría externa.</strong> El CLI fusiona las calibraciones en la telemetría, pero no actúa sobre ellas. Si un auditor califica el Charter con un 4, el Charter no se reabre automáticamente: el operador decide si reabrir, si argumentar, si declararlo <em>acceptable-with-known-debt</em>. Esa decisión es la disciplina; automatizarla la destruiría.</li>
<li class=""><strong>La invocación de los modelos.</strong> Como ya argumenté arriba: la pausa donde el operador copia el prompt es exactamente donde decide qué modelo usar, qué prompt ajustar, si la pregunta tal cual está formulada le parece justa. Esa pausa es feature, no bug.</li>
</ul>
<p>El criterio que recorre las tres es uno solo: <em>automatizar lo que sea reversible y mecánico; preservar como manual lo que sea juicio</em>. Cuarenta segundos de copy-paste no son demasiados si compran que el juicio sigue siendo humano.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="7-cierre">7. Cierre<a href="https://straymark.dev/es/blog/charters-and-the-external-audit-cycle#7-cierre" class="hash-link" aria-label="Enlace directo al 7. Cierre" title="Enlace directo al 7. Cierre" translate="no">​</a></h2>
<p>Lo que aprendí del proceso, en cuatro tesis:</p>
<ol>
<li class="">
<p><strong>Una práctica que funciona empíricamente no necesita ser reinventada para canonizarse.</strong> Sentinel hizo el trabajo de validación en abril; mayo solo lo trasladó al framework. La cristalización es traslado, no diseño desde cero.</p>
</li>
<li class="">
<p><strong>Cuando la propuesta está bien escrita, la implementación es ejecución.</strong> Tres releases en un día solo son posibles cuando todas las decisiones quedaron cerradas antes de tocar código. El principio #6 lo dice más prosaicamente, pero esto es lo que significa.</p>
</li>
<li class="">
<p><strong>No todo lo automatizable debe automatizarse.</strong> La decisión A1 — el CLI orquesta pero no invoca APIs — es la versión técnica de una decisión filosófica: el humano-en-el-loop no es legacy del que hay que deshacerse, es feature que sostiene la disciplina.</p>
</li>
<li class="">
<p><strong>La identidad del framework se define tanto por lo que hace como por lo que no hace.</strong> <em>"No es un LLM gateway"</em> es una de las pocas frases del principio #10 que vale la pena recordar literal. Lo que StrayMark hace lo hace bien porque hay muchas cosas que se niega a hacer.</p>
</li>
</ol>
<p>Sigue, en el siguiente post, el episodio metodológico que conecta con el inicio mismo del blog — <em>Issue #113: Charters invisibles para los agentes</em> — donde el framework descubre que crear comandos y schemas no basta si la <em>superficie</em> del repo no le habla al agente. Es el contrapeso natural a este post: aquí hablamos de lo que se canonizó; allá hablamos de lo que no se vio.</p>
<hr>
<p><em>Anclas: PRs <a href="https://github.com/StrangeDaysTech/straymark/pull/65" target="_blank" rel="noopener noreferrer" class="">#65</a> · <a href="https://github.com/StrangeDaysTech/straymark/pull/68" target="_blank" rel="noopener noreferrer" class="">#68</a> · <a href="https://github.com/StrangeDaysTech/straymark/pull/69" target="_blank" rel="noopener noreferrer" class="">#69</a> (Charters first-class). Propuestas <a href="https://github.com/StrangeDaysTech/straymark/blob/main/docs/decisions/proposals/2026-05-03-audit-skills-design.md" target="_blank" rel="noopener noreferrer" class=""><code>audit-skills-design.md</code></a> · <a href="https://github.com/StrangeDaysTech/straymark/blob/main/docs/decisions/proposals/2026-05-03-audit-skills-rollout.md" target="_blank" rel="noopener noreferrer" class=""><code>audit-skills-rollout.md</code></a> · <a href="https://github.com/StrangeDaysTech/straymark/blob/main/docs/decisions/proposals/2026-05-04-audit-cli-flow.md" target="_blank" rel="noopener noreferrer" class=""><code>audit-cli-flow.md</code></a> · <a href="https://github.com/StrangeDaysTech/straymark/blob/main/docs/decisions/proposals/2026-05-03-cli-roadmap.md" target="_blank" rel="noopener noreferrer" class=""><code>cli-roadmap.md</code></a> (decisión A1 §0). Releases fw-4.4.0 → fw-4.9.0.</em></p>
<p><em>Este documento fue elaborado con asistencia de herramientas de IA generativa (Claude 4.7); toda la responsabilidad del contenido recae en el autor humano.</em></p>]]></content:encoded>
            <category>straymark</category>
            <category>charters</category>
            <category>audit</category>
            <category>cli</category>
            <category>governance</category>
        </item>
        <item>
            <title><![CDATA[Seis Planes para una tesis (y el rename a Charter)]]></title>
            <link>https://straymark.dev/es/blog/six-plans-and-the-rename-to-charter</link>
            <guid>https://straymark.dev/es/blog/six-plans-and-the-rename-to-charter</guid>
            <pubDate>Thu, 30 Apr 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[Primer experimento sistemático y el día que Plan se llamó Charter]]></description>
            <content:encoded><![CDATA[<p><em>Seis Planes sobre el papel, cinco en la práctica — el primer experimento sistemático de Sentinel entre el 25 y el 28 de abril. El ciclo que convirtió un patrón artesanal en Charters, la unidad acotada de trabajo del framework.</em></p>
<!-- -->
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="1-una-nota-al-pie-que-dice-mucho">1. Una nota al pie que dice mucho<a href="https://straymark.dev/es/blog/six-plans-and-the-rename-to-charter#1-una-nota-al-pie-que-dice-mucho" class="hash-link" aria-label="Enlace directo al 1. Una nota al pie que dice mucho" title="Enlace directo al 1. Una nota al pie que dice mucho" translate="no">​</a></h2>
<p>En la propuesta <code>charter-telemetry.md</code>, escrita el 30 de abril de 2026, hay una nota terminológica al inicio:</p>
<blockquote>
<p><em>"Lo que este documento llama 'Charter' se llamó 'Plan' en el experimento Sentinel (PLAN-01..06). Los datos empíricos citados abajo se refieren a esos Plans históricos por su nombre original; el shape del schema y los ejemplos prospectivos usan el nombre going-forward 'Charter'."</em></p>
</blockquote>
<p>Es una nota al pie, técnica, sin drama. Pero registra el momento exacto en que el artefacto cambió de nombre — y, más interesante, registra una decisión de archivo que el blog también respeta: lo que se llamó <em>Plan</em> en su momento se sigue llamando <em>Plan</em> en los registros originales. Reescribir el nombre hacia atrás sería falsificar el rastro.</p>
<p>Este post cubre dos cosas que pasaron en cinco días: el primer experimento sistemático del framework — los seis Planes de Sentinel, ejecutados entre el 25 y el 28 de abril — y el rename que vino después, el 30. No son dos eventos separados. Uno trajo al otro.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="2-seis-planes-en-el-papel-cinco-en-la-realidad">2. Seis Planes en el papel, cinco en la realidad<a href="https://straymark.dev/es/blog/six-plans-and-the-rename-to-charter#2-seis-planes-en-el-papel-cinco-en-la-realidad" class="hash-link" aria-label="Enlace directo al 2. Seis Planes en el papel, cinco en la realidad" title="Enlace directo al 2. Seis Planes en el papel, cinco en la realidad" translate="no">​</a></h2>
<p>El experimento se diseñó con seis Planes (<code>PLAN-01</code> a <code>PLAN-06</code>) y se ejecutó con cinco. PLAN-04 nunca corrió: quedó como un catálogo de siete <em>features</em> diferidas, una lista de cosas que se quería hacer pero que el ciclo de pruebas no alcanzaba a cubrir. Es honesto decirlo así, porque el propio documento que valida la tesis (<code>thesis-validation.md</code>) lo registra abiertamente en su tabla resumen:</p>















































<table><thead><tr><th>Plan</th><th>Escala</th><th>Lo que hizo</th><th>Formato</th></tr></thead><tbody><tr><td>PLAN-01</td><td>XS</td><td>Deploy de docs de gobernanza</td><td>v1</td></tr><tr><td>PLAN-02</td><td>S</td><td>Endpoint admin (<code>gcp-resource</code>)</td><td>v1</td></tr><tr><td>PLAN-03</td><td>XS</td><td>Bumps de contrato</td><td>v1</td></tr><tr><td>PLAN-05</td><td>M</td><td>Per-service anomaly thresholds</td><td><strong>v2</strong></td></tr><tr><td>PLAN-06</td><td>XS</td><td>Recompute manual de baseline</td><td><strong>v3</strong></td></tr><tr><td><em>(PLAN-04 catalog)</em></td><td>—</td><td>Roadmap de 7 features diferidas, no ejecutado</td><td>—</td></tr></tbody></table>
<p>Cinco Planes, cuatro escalas distintas: tres XS, una S, una M. Dominios deliberadamente heterogéneos — un deploy operativo, dos endpoints administrativos, un bump de contrato, una feature de backend con lógica de configuración. No era un benchmark sintético. Era el código real de Sentinel del 25 al 28 de abril, partido en unidades acotadas y auditado pieza por pieza con tres modelos (Copilot, Gemini, Claude) actuando como auditores externos.</p>
<p>El sexto Plan no haberse ejecutado importa por dos razones. La primera es la obvia: el experimento se quedó sin tiempo. La segunda es más interesante: PLAN-04 era el único Plan grande del lote — siete features acumuladas, sin acotamiento natural. Que justamente ese Plan fuera el que no entró ya estaba diciendo algo sobre el tamaño que podía tolerar el formato. Los Planes pequeños sí; los Planes-roadmap, no. Esa lección se canonizó después, sin que nadie tuviera que escribirla: los Charters de StrayMark hoy son <em>"unidades acotadas, de horas a días, una rama"</em>, no roadmaps trimestrales.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="3-el-experimento-iteró-sobre-sí-mismo">3. El experimento iteró sobre sí mismo<a href="https://straymark.dev/es/blog/six-plans-and-the-rename-to-charter#3-el-experimento-iter%C3%B3-sobre-s%C3%AD-mismo" class="hash-link" aria-label="Enlace directo al 3. El experimento iteró sobre sí mismo" title="Enlace directo al 3. El experimento iteró sobre sí mismo" translate="no">​</a></h2>
<p>Cinco Planes ejecutados produjeron tres formatos distintos. No fue por capricho; fue porque cada ciclo dejó al descubierto algo que el formato anterior no capturaba.</p>
<ul>
<li class="">
<p><strong>v1</strong> — los tres primeros Planes (<code>01</code>, <code>02</code>, <code>03</code>) corrieron con un formato originario. Se identificaron cinco patrones recurrentes en los AILOGs de auditoría, pero ninguno estaba formalizado en una plantilla. Existían como costumbre, no como contrato.</p>
</li>
<li class="">
<p><strong>v2</strong> — para PLAN-05, esos cinco patrones se materializaron en <code>TEMPLATE.md</code>, más una sección <em>"Format conventions"</em> en el README. Doc-only: nada ejecutable todavía. La hipótesis: si el formato es explícito, los auditores externos convergen mejor. El propio AILOG-020 lo dice sin adorno: <em>"Los patrones internos que llevan tiempo aplicándose pero no tienen nombre quedan invisibles a auditores externos. Nombrarlos formalmente convierte la práctica en señal pública."</em></p>
</li>
<li class="">
<p><strong>v3</strong> — para PLAN-06, se sumó un patrón nuevo (auto-checklist drift) y, esta vez, <em>tooling ejecutable</em>: <code>scripts/check-plan-drift.sh</code>, ~145 líneas de bash que validan si la entrega real coincide con lo declarado en el Plan. Por primera vez el formato dejó de ser solo prosa y empezó a tener un verificador.</p>
</li>
</ul>
<p>Lo que me interesa señalar aquí es la forma de la curva. v1 capturó práctica latente. v2 le puso nombre. v3 le puso un programa que la chequea. Es el arco completo de cualquier estandarización útil — y lo recorrimos en cinco Planes, no en cinco años.</p>
<p>Es también la primera evidencia concreta de algo que dos meses después se nombraría explícitamente como Pattern 1 (<em>pre-declare refresh</em>) y Pattern 2 (<em>amend-on-emergence</em>) en <code>CHARTER-CHAIN-EVOLUTION.md</code>. Lo que ahí se canonizó como meta-patrón empezó aquí, en abril, como costumbre sin nombre.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="4-la-evidencia-más-dura-auditores-externos-convergiendo">4. La evidencia más dura: auditores externos convergiendo<a href="https://straymark.dev/es/blog/six-plans-and-the-rename-to-charter#4-la-evidencia-m%C3%A1s-dura-auditores-externos-convergiendo" class="hash-link" aria-label="Enlace directo al 4. La evidencia más dura: auditores externos convergiendo" title="Enlace directo al 4. La evidencia más dura: auditores externos convergiendo" translate="no">​</a></h2>
<p>El supuesto más cargado de la tesis era: <em>"notas estructuradas reducen modos de falla, y se nota cuando auditores externos miran"</em>. La forma de probarlo: enviar el output de cada Plan — los archivos modificados, el AILOG, el Plan-doc bajo TEMPLATE — a tres auditores que no participaron en el desarrollo (Copilot, Gemini, y un análisis crítico de Claude) y comparar las calificaciones agregadas.</p>
<p>El número que <code>thesis-validation.md</code> reporta para PLAN-05 (el primer Plan bajo v2 y bajo escala M) es claro:</p>
<blockquote>
<p><em>"Mejor calibración combinada de auditores en 5 ciclos (Copilot 9.25, Gemini 9.5). Hipótesis acumulada confirmada: TEMPLATE v2 + AILOGs ricos reducen el espacio de ambigüedad para auditoría externa."</em></p>
</blockquote>
<p>Dos modelos heterogéneos, instrucciones diferentes, convergiendo en torno a 9.3 sobre 10 — sobre el Plan más grande del lote, además, no el más chico. Eso es señal, no ruido. Y se replicó al ejercitar el <code>check-plan-drift.sh</code> de v3:</p>
<blockquote>
<p><em>"PLAN-05 (con drifts conocidos): script reporta 3 omitted files: <code>evaluator_test.go</code> (F4), <code>repository.go</code> (F1/R6), <code>statuscenter/service.go</code> (F5) — exactamente los 3 drifts que Copilot+Gemini capturaron en sus auditorías. Cero falsos positivos."</em></p>
</blockquote>
<p>El script automatizado y los dos auditores externos coincidieron exactamente en qué archivos del Plan habían quedado a deber. No es un argumento sobre que el script sea inteligente — es bash y <em>grep</em>, no podría ser más tonto. Es un argumento sobre que el formato del Plan, ya formalizado, hace que <em>cualquier inspector</em> (humano, agente, script) vea las mismas cosas. La disciplina estructurada no requiere inteligencia para auditarse: requiere claridad.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="5-lo-que-el-experimento-no-demostró">5. Lo que el experimento <em>no</em> demostró<a href="https://straymark.dev/es/blog/six-plans-and-the-rename-to-charter#5-lo-que-el-experimento-no-demostr%C3%B3" class="hash-link" aria-label="Enlace directo al 5-lo-que-el-experimento-no-demostró" title="Enlace directo al 5-lo-que-el-experimento-no-demostró" translate="no">​</a></h2>
<p>Esta es la sección que más me interesa que quede registrada, porque es donde se prueba si el blog está dispuesto a ser honesto.</p>
<p><code>thesis-validation.md</code> se diseñó explícitamente para romper la tesis, no para defenderla. La primera línea del documento dice:</p>
<blockquote>
<p><em>"Este documento confronta esa tesis con datos. No la defiende; intenta romperla. El objetivo es que un lector que no compró la tesis pueda, leyendo solo este texto, decidir si la evidencia disponible la sostiene, la matiza o la refuta."</em></p>
</blockquote>
<p>El veredicto final, con los seis supuestos de la tesis enfrentados a la evidencia, es éste:</p>








































<table><thead><tr><th>#</th><th>Supuesto</th><th>Veredicto</th></tr></thead><tbody><tr><td>1</td><td>Vibe coding no escala</td><td>Validado parcialmente <em>(sin brazo de control)</em></td></tr><tr><td>2</td><td>Notas estructuradas reducen modos de falla</td><td>Validado</td></tr><tr><td>3</td><td>Subproducto regulatorio sin trabajo extra</td><td>Validado <em>(pendiente prueba con auditor humano real)</em></td></tr><tr><td>4</td><td>Aprobaciones rara vez binarias</td><td>Sin evidencia — pendiente proyecto multi-actor</td></tr><tr><td>5</td><td>Stage &gt; commit como unidad de trazabilidad</td><td>Validado</td></tr><tr><td>6</td><td>Firma in-situ &gt; reconstrucción posterior</td><td>Validado parcialmente <em>(sin firma criptográfica probada)</em></td></tr></tbody></table>
<p>Tres supuestos validados completos, dos parciales, uno <em>sin evidencia</em>, cero refutados. El supuesto sobre aprobaciones no binarias se quedó sin probar porque Sentinel es un proyecto de un solo responsable; haría falta un equipo real con varios firmantes para ejercitarlo. Y la firma criptográfica — Sigstore, hash-chaining, las garantías técnicas de un append-only log — no se ejercitó porque ningún Plan tocó esa parte del flujo. Eso queda en el documento como <em>gap</em> explícito, no como afirmación al aire.</p>
<p>Lo que el experimento no demostró importa más que lo que sí demostró. Si en lugar de cinco veredictos honestos hubiéramos publicado seis verdes, el blog sería marketing. La forma de evitarlo es decir, sin atenuar: aquí hay supuestos sobre los que no tenemos evidencia, y un proyecto de un solo operador no puede generarla. Otros la generarán; el framework irá madurando con esos datos.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="6-por-qué-plan-se-volvió-charter">6. Por qué Plan se volvió Charter<a href="https://straymark.dev/es/blog/six-plans-and-the-rename-to-charter#6-por-qu%C3%A9-plan-se-volvi%C3%B3-charter" class="hash-link" aria-label="Enlace directo al 6. Por qué Plan se volvió Charter" title="Enlace directo al 6. Por qué Plan se volvió Charter" translate="no">​</a></h2>
<p>El rename del 30 de abril no fue de marketing. La razón está escrita literal en <code>WHAT-IS-A-CHARTER.md</code>:</p>
<blockquote>
<p><em>"GitHub SpecKit already uses the word 'plan' (<code>/speckit.plan</code>, <code>plan.md</code>) for a different artifact, and the nominal collision generated friction in adopter docs that combine both flows."</em></p>
</blockquote>
<p>SpecKit ya tenía un <code>plan.md</code>. StrayMark también. En la documentación de un adopter que usara ambos, <em>plan</em> significaba cosas distintas en párrafos contiguos. El rename existió para arreglar esa colisión.</p>
<p>Pero detrás del pragmatismo hay un matiz que sí vale la pena nombrar. Los dos artefactos <em>son</em> distintos, y la distinción es estructural:</p>






























<table><thead><tr><th></th><th><strong><code>plan.md</code> de SpecKit</strong></th><th><strong>Charter de StrayMark</strong></th></tr></thead><tbody><tr><td>Granularidad</td><td>Feature completa (semanas, varias stories)</td><td>Unidad acotada (horas a días, una rama)</td></tr><tr><td>Contenido dominante</td><td>Stack, dependencias, estructura del proyecto, constitution gates</td><td>Archivos concretos a tocar, comandos de verificación, riesgos <code>R&lt;N&gt;</code></td></tr><tr><td>Validación</td><td>Constitution Check (gate <em>ex-ante</em>)</td><td>Drift-check + auditoría externa (gates <em>ex-post</em>)</td></tr><tr><td>Optimización</td><td><em>Claridad anticipada</em></td><td><em>Trazabilidad ex-post</em></td></tr></tbody></table>
<p>Lo que SpecKit llama <em>plan</em> se parece más a un ADR con esqueleto arquitectónico. Lo que StrayMark llama <em>Charter</em> se parece más a una task-card con verificación contractual y anclaje de auditoría. Son artefactos complementarios, no competidores; eso lo hace explícito <code>SPECKIT-CHARTER-BRIDGE.md</code> después, en mayo. Pero la nomenclatura tenía que dejar de chocar antes de que se pudiera hablar de complementariedad.</p>
<p>La parte que me parece importante destacar es la decisión adyacente: los registros históricos de Sentinel — los AILOGs, las telemetrías, el <code>check-plan-drift.sh</code>, las carpetas <code>sentinel/docs/plans/</code> — conservan el nombre <em>Plan</em>. El propio <code>WHAT-IS-A-CHARTER.md</code> lo argumenta así:</p>
<blockquote>
<p><em>"Sentinel's historical records (Plans 01–06, <code>sentinel/docs/plans/</code>, <code>sentinel/scripts/check-plan-drift.sh</code>, AILOGs and YAML telemetries <code>PLAN-NN.telemetry.yaml</code>) preserve the original name — they are empirical evidence of a specific moment in time, and rewriting history would falsify the record."</em></p>
</blockquote>
<p><em>Rewriting history would falsify the record.</em> Esa frase es, para mí, el verdadero corazón del rename. El framework existe para preservar rastro, no para reescribirlo. Cuando el artefacto cambió de nombre, el cambio fue prospectivo: a partir del 30 de abril, los nuevos se llaman Charters. Los viejos, los del experimento, siguen siendo Planes. La inconsistencia es deliberada, y la inconsistencia es la evidencia.</p>
<p>El otro acoplamiento del 30 de abril — la propuesta de telemetría — vino el mismo día por razones que ahora resultan obvias: si el patrón emergente merecía un nombre nuevo, también merecía medición estructurada. El schema <code>charter-telemetry.schema.v0.json</code>, con sus campos sobre tiempo invertido, drifts detectados, escala, dominio, es la maquinaria que ejecuta hoy lo que en Sentinel todavía se medía a mano en YAML. Plan se renombró a Charter el mismo día en que se decidió empezar a contar Charters.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="7-cierre">7. Cierre<a href="https://straymark.dev/es/blog/six-plans-and-the-rename-to-charter#7-cierre" class="hash-link" aria-label="Enlace directo al 7. Cierre" title="Enlace directo al 7. Cierre" translate="no">​</a></h2>
<p>Lo que aprendí del proceso, en cuatro tesis:</p>
<ol>
<li class="">
<p><strong>El experimento se diseñó para romperse, no para confirmarse.</strong> <em>"No la defiende; intenta romperla"</em> — eso fue, literal, la consigna del documento que validó la tesis. Cualquier blog técnico que se respete tiene que tolerar esa formulación.</p>
</li>
<li class="">
<p><strong>Cinco Planes ejecutados, de seis diseñados, en cuatro días.</strong> El que no se ejecutó (el más grande, un roadmap de siete features) fue, sin querer, la primera evidencia de qué tamaño tolera la unidad. Hoy los Charters son acotados por contrato. En abril, lo eran por accidente.</p>
</li>
<li class="">
<p><strong>El formato evolucionó dentro del experimento mismo: de costumbre, a plantilla, a script.</strong> Los cinco Planes produjeron tres versiones del formato. La curva de v1 → v2 → v3 es la curva de cualquier estandarización útil — solo que comprimida.</p>
</li>
<li class="">
<p><strong>El rename fue de pragmatismo, no de marketing. Y la preservación histórica fue de principio.</strong> <em>Plan</em> siguió llamándose <em>Plan</em> en Sentinel, donde así se llamó. <em>Charter</em> empezó a usarse de abril para adelante. El framework no reescribe su propio archivo: por eso vale la pena rastrearlo.</p>
</li>
</ol>
<p>Sigue, en el siguiente post, dos hitos cercanos que codifican capacidades cualitativamente nuevas: <em>Charters como entidad de primera clase</em> (PR #65, fw-4.4.0) y <em>el audit cycle externo multi-modelo</em> (<code>audit-skills-design</code>, <code>audit-cli-flow</code>, releases fw-4.7 → fw-4.9). Es donde el experimento de Sentinel se convirtió en funcionalidad de CLI.</p>
<hr>
<p><em>Anclas: propuestas <a href="https://github.com/StrangeDaysTech/straymark/blob/main/docs/decisions/proposals/2026-04-30-thesis-validation.md" target="_blank" rel="noopener noreferrer" class=""><code>thesis-validation.md</code></a> y <a href="https://github.com/StrangeDaysTech/straymark/blob/main/docs/decisions/proposals/2026-04-30-charter-telemetry.md" target="_blank" rel="noopener noreferrer" class=""><code>charter-telemetry.md</code></a> (ambas 2026-04-30). Definición canónica del Charter: <a href="https://github.com/StrangeDaysTech/straymark/blob/main/docs/contributors/WHAT-IS-A-CHARTER.md" target="_blank" rel="noopener noreferrer" class=""><code>WHAT-IS-A-CHARTER.md</code></a>. Schema operacional: <code>dist/.straymark/schemas/charter-telemetry.schema.v0.json</code>.</em></p>
<p><em>Este documento fue elaborado con asistencia de herramientas de IA generativa (Claude 4.7); toda la responsabilidad del contenido recae en el autor humano.</em></p>]]></content:encoded>
            <category>straymark</category>
            <category>sentinel</category>
            <category>charters</category>
            <category>metodología</category>
            <category>governance</category>
        </item>
        <item>
            <title><![CDATA[Explorando el framework]]></title>
            <link>https://straymark.dev/es/blog/exploring-the-framework</link>
            <guid>https://straymark.dev/es/blog/exploring-the-framework</guid>
            <pubDate>Mon, 27 Apr 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[La TUI que produjo visibilidad sin proponérselo]]></description>
            <content:encoded><![CDATA[<p><em>Para abril de 2026 el framework tenía ~50 archivos Markdown gobernados y se había vuelto opaco. <code>straymark explore</code> — un TUI que renderiza todo el repo como superficie navegable — nació tres semanas antes de revelar accidentalmente el outlier del Post 8. Las herramientas nuevas producen visibilidad sin proponérselo.</em></p>
<!-- -->
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="1-la-herramienta-que-dos-semanas-después-reveló-el-outlier">1. La herramienta que dos semanas después reveló el outlier<a href="https://straymark.dev/es/blog/exploring-the-framework#1-la-herramienta-que-dos-semanas-despu%C3%A9s-revel%C3%B3-el-outlier" class="hash-link" aria-label="Enlace directo al 1. La herramienta que dos semanas después reveló el outlier" title="Enlace directo al 1. La herramienta que dos semanas después reveló el outlier" translate="no">​</a></h2>
<p>El Post 8 de este blog cubrió un episodio muy específico: el descubrimiento del único archivo del framework cuyo idioma canónico era el español. El operador no lo encontró por inspección sistemática; lo encontró ejecutando <code>straymark explore --lang es</code> durante una preparación de auditoría y notando, visualmente, que un template estaba escrito al revés respecto a los demás. La frase de aquel post fue:</p>
<blockquote>
<p><em>"Una nueva superficie del framework (la TUI) puso todos los archivos en visión simultánea, y la inconsistencia se hizo evidente como cuando uno ordena los libros del librero y nota que uno tiene el lomo al revés."</em></p>
</blockquote>
<p>Este post cubre la herramienta. La TUI <code>straymark explore</code> nació casi tres semanas antes del descubrimiento que reveló — el 25 de abril de 2026 en <code>cli-3.4.0</code> — y maduró en cuatro releases más, todos cerrados en menos de 48 horas. No es un post sobre código. Es un post sobre una pieza específica de tooling que ratifica una tesis que el blog ya nombró antes: las herramientas nuevas producen visibilidad sin proponérselo.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="2-por-qué-un-tui-en-un-framework-de-markdown">2. Por qué un TUI en un framework de Markdown<a href="https://straymark.dev/es/blog/exploring-the-framework#2-por-qu%C3%A9-un-tui-en-un-framework-de-markdown" class="hash-link" aria-label="Enlace directo al 2. Por qué un TUI en un framework de Markdown" title="Enlace directo al 2. Por qué un TUI en un framework de Markdown" translate="no">​</a></h2>
<p>A finales de abril de 2026, el framework tenía algo así como cincuenta archivos Markdown gobernados — <code>PRINCIPLES.md</code>, <code>AGENT-RULES.md</code>, <code>DOCUMENTATION-POLICY.md</code>, <code>QUICK-REFERENCE.md</code>, <code>SPECKIT-CHARTER-BRIDGE.md</code>, plus templates en <code>dist/.straymark/templates/</code>, plus audit prompts, plus las versiones en tres idiomas de cada uno (<code>i18n/es/</code>, <code>i18n/zh-CN/</code>). Todo en disco, todo navegable con <code>find</code> y <code>cat</code>, todo perfectamente accesible.</p>
<p>Y, al mismo tiempo, todo invisible. Para un adoptante que clonaba el framework por primera vez, la primera pregunta no era <em>"¿dónde está la regla N?"</em>. Era <em>"¿qué hay aquí?"</em>. Y un <code>ls</code> recursivo no responde esa pregunta — la abruma. Un <code>grep</code> requiere saber qué buscar. Un editor abre un archivo a la vez. El framework había llegado al tamaño donde su propia superficie se había vuelto opaca.</p>
<p><code>straymark explore</code> nació exactamente para resolver eso: una superficie navegable que respondiera <em>"¿qué hay aquí?"</em> en tres segundos. No un IDE; no un sistema de docs estilo Read-the-Docs; no un site estático. Un TUI — terminal user interface — que se ejecuta sobre el repo del adoptante, indexa los archivos canónicos del framework, los muestra agrupados por categoría, y permite leerlos con un visor de Markdown coloreado dentro de la terminal.</p>
<p>La decisión de hacer TUI y no web está alineada con dos cosas que el blog ya argumentó. Primero, el principio #10 del Post 4 — <em>"StrayMark no es un LLM gateway"</em> — generaliza a <em>"StrayMark no es lo que ya hace otra cosa"</em>. No competimos con MkDocs ni con Material for MkDocs. Segundo, la decisión A1 del mismo Post 4: orchestration-only. El TUI no requiere servidor, no requiere build paso, no requiere conexión: corre sobre el repo del adoptante, donde ya está el framework. Es la pieza más humilde que podía resolver el problema.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="3-lo-que-entró-en-cli-340">3. Lo que entró en <code>cli-3.4.0</code><a href="https://straymark.dev/es/blog/exploring-the-framework#3-lo-que-entr%C3%B3-en-cli-340" class="hash-link" aria-label="Enlace directo al 3-lo-que-entró-en-cli-340" title="Enlace directo al 3-lo-que-entró-en-cli-340" translate="no">​</a></h2>
<p>El <a href="https://github.com/StrangeDaysTech/straymark/pull/57" target="_blank" rel="noopener noreferrer" class="">PR #57</a> del 25 de abril, fusionado como <code>cli-3.4.0</code>, hizo tres cosas concretas:</p>
<ul>
<li class="">Introdujo el comando <code>straymark explore</code>. Layout de dos paneles cuando la terminal tiene 100 columnas o más: navegación a la izquierda (30%), documento a la derecha (70%). Paneles más estrechos colapsan a un solo panel para terminales angostas. Status bar al pie con los atajos relevantes.</li>
<li class="">Indexó los archivos canónicos del framework en una jerarquía navegable: governance docs (<code>AGENT-RULES.md</code>, <code>DOCUMENTATION-POLICY.md</code>, ...), templates (<code>dist/.straymark/templates/</code>), audit prompts, y los directorios del adoptante (<code>docs/charters/</code>, <code>.straymark/07-ai-audit/</code>, ...). Cada nodo expansible con <code>Enter</code>.</li>
<li class="">Cableó el resolver i18n. La opción <code>--lang &lt;code&gt;</code> permite ejecutar <code>straymark explore --lang es</code> y obtener todos los governance docs en español <em>si</em> hay traducción disponible. Si no la hay, fallback silencioso al canónico EN. La descripción literal del commit:</li>
</ul>
<blockquote>
<p><em>"Wire <code>language</code> config and a new <code>--lang</code> flag through the explore TUI so framework governance docs are served from <code>i18n/&lt;lang&gt;/</code> when a translation exists, falling back silently to English otherwise."</em></p>
</blockquote>
<p>La parte del resolver i18n importa más que el TUI en sí. Hasta <code>cli-3.4.0</code>, el helper <code>resolve_localized_path</code> lo usaba solo <code>straymark new</code> (para resolver qué template inyectar al adoptante en el idioma correcto). El PR #57 lo extrajo a <code>cli/src/utils.rs:146</code> como helper compartido, de modo que <strong>una sola definición de cómo se resuelven los overlays <code>i18n/&lt;lang&gt;/</code></strong> sostiene tanto el comando <code>new</code> como el comando <code>explore</code>. El comportamiento queda predecible para el adoptante: si traduce un template a <code>i18n/es/</code>, el TUI lo va a mostrar igual que la generación lo va a usar. Sin sorpresas.</p>
<p>El renderizado del Markdown usa <code>pulldown-cmark</code> para el parser y los widgets de <code>ratatui</code> para pintar. Sintaxis coloreada, code blocks con borde, tablas con bordes redondeados, headings indentados según nivel. No es ostentoso; es legible.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="4-cuatro-refinamientos-en-treinta-y-seis-horas">4. Cuatro refinamientos en treinta y seis horas<a href="https://straymark.dev/es/blog/exploring-the-framework#4-cuatro-refinamientos-en-treinta-y-seis-horas" class="hash-link" aria-label="Enlace directo al 4. Cuatro refinamientos en treinta y seis horas" title="Enlace directo al 4. Cuatro refinamientos en treinta y seis horas" translate="no">​</a></h2>
<p>Lo que pasó entre el 25 y el 27 de abril es lo que el Post 9 nombró meses después como propiedad del proceso: cuando la propuesta es bien escrita, la implementación es ejecución. Cuatro PRs más, cerrados en menos de 36 horas, llevaron el TUI de "funciona" a "está terminado":</p>



































<table><thead><tr><th>PR</th><th>Tag</th><th>Hora</th><th>Qué agregó</th></tr></thead><tbody><tr><td><a href="https://github.com/StrangeDaysTech/straymark/pull/60" target="_blank" rel="noopener noreferrer" class="">#60</a></td><td>cli-3.5.0</td><td>25 abr 22:36</td><td><strong>Live language switcher.</strong> Tecla <code>L</code> cicla el idioma del display sin salir del TUI: <code>en → es → zh-CN → en</code>. El índice se reconstruye in-place.</td></tr><tr><td><a href="https://github.com/StrangeDaysTech/straymark/pull/61" target="_blank" rel="noopener noreferrer" class="">#61</a></td><td>cli-3.5.0 (mismo release)</td><td>25 abr 23:41</td><td><strong>OS locale auto-detect.</strong> Si el adoptante no tiene <code>config.yml</code>, el TUI lee <code>$LC_ALL</code> / <code>$LANG</code> y mapea el POSIX locale (e.g. <code>es_MX.UTF-8</code> → <code>es</code>) al idioma soportado más cercano.</td></tr><tr><td><a href="https://github.com/StrangeDaysTech/straymark/pull/62" target="_blank" rel="noopener noreferrer" class="">#62</a></td><td>cli-3.5.1</td><td>26 abr 00:07</td><td><strong>Metadata panel traducido.</strong> 25 nuevas entradas i18n para labels y títulos, con padding visual para mantener alineación entre idiomas.</td></tr><tr><td><a href="https://github.com/StrangeDaysTech/straymark/pull/63" target="_blank" rel="noopener noreferrer" class="">#63</a></td><td>cli-3.5.2</td><td>26 abr 00:13</td><td><strong>Cleanup de keybindings.</strong> Elimina los aliases vim <code>l</code> y <code>h</code> no documentados (la <code>l</code> chocaba con <code>L</code> del language switcher). Mantiene <code>j/k/g/G/n/N</code> documentados.</td></tr></tbody></table>
<p>La velocidad del arco repite el patrón. Los cinco PRs de fw-4.11.0 que cubrió el Post 6 (rebrand a StrayMark) se cerraron en cuarenta y tres minutos. Los tres releases del audit cycle externo que cubrió el Post 4 se cerraron en un día. La curva del TUI es parecida: el diseño quedó claro en el PR #57, y los refinamientos vinieron cuando el operador empezó a usar el comando con frecuencia y notó las fricciones.</p>
<p>La anécdota que vale la pena dejar registrada es el <code>cli-3.5.2</code>: las teclas <code>l</code> y <code>h</code> que eliminó eran aliases vim — el operador las usa de hábito muscular en su editor. Pero cuando se introdujo el language switcher en mayúsculas (<code>L</code>) horas antes, la <code>l</code> minúscula y la <code>L</code> mayúscula compartían la misma tecla física, y la transición visual era confusa. La solución fue eliminar los aliases no documentados: el ortografía completa (<code>j/k/g/G</code>) se mantiene; las abreviaturas que duplicaban funciones desaparecen. Es un detalle UX pequeño que ilustra cómo las decisiones del TUI van afinando contra el uso real, no contra teoría de UX.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="5-lo-que-la-tui-reveló-dos-semanas-después">5. Lo que la TUI reveló dos semanas después<a href="https://straymark.dev/es/blog/exploring-the-framework#5-lo-que-la-tui-revel%C3%B3-dos-semanas-despu%C3%A9s" class="hash-link" aria-label="Enlace directo al 5. Lo que la TUI reveló dos semanas después" title="Enlace directo al 5. Lo que la TUI reveló dos semanas después" translate="no">​</a></h2>
<p>Aquí el post recoge el hilo del Post 8 desde el otro extremo. Lo que <code>cli-3.4.0</code> añadió al framework no fue solo un comando de navegación; fue una <strong>superficie de visualización simultánea</strong>. Es decir: antes del TUI, los archivos del framework existían pero se leían uno a uno. Después del TUI, podían verse todos a la vez, agrupados, etiquetados, en el mismo modo de presentación.</p>
<p>Eso cambia lo que el operador puede notar.</p>
<p>El 12 de mayo, dos semanas y media después del merge de <code>cli-3.4.0</code>, el operador ejecutó <code>straymark explore --lang es</code> antes de un ciclo de auditoría externa. Llegó al grupo de "audit prompts". Lo abrió. Y notó algo que llevaba existiendo un año: el <code>audit-prompt.md</code> en root del directorio estaba escrito <em>en español</em>, mientras todos los demás archivos canónicos del framework tenían inglés en root y overlays <code>i18n/es/</code>. Un solo archivo, al revés respecto a la convención.</p>
<p>El detalle no se descubrió por revisión sistemática. Se descubrió por contraste visual. Es exactamente lo que el Post 8 §3 codificó como tesis:</p>
<blockquote>
<p><em>"Las herramientas nuevas producen visibilidad."</em></p>
</blockquote>
<p>El TUI no causó el outlier — el outlier existía desde el primer commit que portó el skill <code>plan-audit</code> de Sentinel al framework canónico (Post 3 lo registra). El TUI tampoco buscó el outlier; no es una herramienta de detección de inconsistencias. Lo único que hizo fue poner todos los archivos en la misma pantalla, en el mismo modo de presentación, y permitir que el ojo humano notara lo que había estado ahí desde el principio. La conclusión que me interesa registrar es estructural: cualquier framework que pase de cincuenta archivos canónicos necesita una superficie de visualización simultánea, no porque la superficie sea pedagógicamente importante en sí, sino porque sin ella ciertas regularidades del repo se vuelven inobservables.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="6-pequeñas-decisiones-técnicas-que-importan">6. Pequeñas decisiones técnicas que importan<a href="https://straymark.dev/es/blog/exploring-the-framework#6-peque%C3%B1as-decisiones-t%C3%A9cnicas-que-importan" class="hash-link" aria-label="Enlace directo al 6. Pequeñas decisiones técnicas que importan" title="Enlace directo al 6. Pequeñas decisiones técnicas que importan" translate="no">​</a></h2>
<p>Tres detalles del diseño del TUI que vale la pena dejar registrados, todos coherentes con principios del framework que el blog ya nombró:</p>
<p><strong>Feature flag <code>tui</code>.</strong> El <code>Cargo.toml</code> del CLI declara el TUI como dependencia opcional (<code>ratatui</code> + <code>crossterm</code> + <code>pulldown-cmark</code> viven detrás del flag <code>tui</code>, habilitado por defecto). Un adoptante que solo quiere <code>init</code>, <code>update</code>, <code>validate</code> puede compilar el binario sin TUI con <code>cargo build --no-default-features</code>. Cierra una sub-decisión arquitectónica que se repite en el framework: dar valor al adoptante por defecto, pero permitirle elegir un binario más liviano cuando el TUI no aporta nada al flow.</p>
<p><strong>Lazy-load de documentos.</strong> El <code>DocIndex</code> mantiene un <code>HashMap&lt;PathBuf, Document&gt;</code> que se llena al abrir cada nodo, no al arrancar. Para un repo con cien archivos governance, esto significa que <code>straymark explore</code> arranca en menos de 200ms y solo lee disco cuando el operador pulsa <code>Enter</code>. La decisión es trivial técnicamente; lo no trivial es que se tomó conscientemente. El TUI no compite con un IDE; compite con un <code>cat</code>. Tiene que sentirse igual de inmediato.</p>
<p><strong>History stack para hipervínculos.</strong> Cuando un documento del framework menciona a otro (e.g., <code>AGENT-RULES.md §3</code> refiere a <code>DOCUMENTATION-POLICY.md §6</code>), el TUI permite saltar al referenciado con un clic — y volver al anterior con <code>Esc</code>. Internamente hay una pila de navegación que restaura el scroll position del documento anterior. Es la pieza que convierte la lectura del framework de <em>"abro un archivo, lo cierro, abro otro"</em> a <em>"sigo una conversación entre documentos sin perder el hilo"</em>. La cantidad de cross-references que el framework tiene hoy — entre principios, agent rules, schemas, templates — hace que esta navegación sea estructuralmente importante, no cosmética.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="7-cierre">7. Cierre<a href="https://straymark.dev/es/blog/exploring-the-framework#7-cierre" class="hash-link" aria-label="Enlace directo al 7. Cierre" title="Enlace directo al 7. Cierre" translate="no">​</a></h2>
<p>Lo que aprendí del proceso, en cuatro tesis:</p>
<ol>
<li class="">
<p><strong>Un framework que pasa cierto tamaño necesita una superficie de visualización simultánea.</strong> No es ergonomía; es condición para que ciertas regularidades del repo sean observables. El Post 8 documentó la consecuencia; este post documenta la herramienta.</p>
</li>
<li class="">
<p><strong>El TUI no causa los descubrimientos; los permite.</strong> El outlier del audit-prompt existía desde mayo del año anterior. Lo único que cambió en abril fue que apareció una pantalla donde se podía ver junto a sus pares. La herramienta no opina sobre el contenido; cambia las condiciones bajo las cuales el ojo humano puede notar regularidades.</p>
</li>
<li class="">
<p><strong>Cuando el diseño está claro, la implementación es cuestión de horas, no de sprints.</strong> Cinco PRs en treinta y seis horas — language-aware, live switcher, OS detection, i18n del panel, cleanup de keybindings — solo son posibles porque el diseño quedó cerrado en el PR #57. Es el mismo patrón de los Posts 4, 6 y 9.</p>
</li>
<li class="">
<p><strong>La decisión técnica más interesante puede ser una flag de compilación.</strong> El feature flag <code>tui</code> declara explícitamente que el TUI es opcional, que el framework sigue funcionando sin él, que el adoptante decide. Esa humildad arquitectónica es la diferencia entre un CLI que asume cómo el adoptante trabaja y un CLI que se ofrece donde puede ser útil.</p>
</li>
</ol>
<p>Con este post el blog cubre el hito <code>H-14</code> que la primera tanda dejó como deuda explícita. Los hitos candidatos restantes que <code>PLAN-INVESTIGACION.md §1.43-55</code> registró — <code>AGENTS.md</code> universal inject, cobertura i18n completa, <code>straymark validate</code> como capa formal, CLA assistant — siguen disponibles para futuras tandas. Sin promesa de cadencia, pero registrados.</p>
<hr>
<p><em>Anclas: PR <a href="https://github.com/StrangeDaysTech/straymark/pull/57" target="_blank" rel="noopener noreferrer" class="">#57</a> — <code>cli-3.4.0</code> (language-aware explore, 25 abr 2026). PRs <a href="https://github.com/StrangeDaysTech/straymark/pull/60" target="_blank" rel="noopener noreferrer" class="">#60</a> · <a href="https://github.com/StrangeDaysTech/straymark/pull/61" target="_blank" rel="noopener noreferrer" class="">#61</a> · <a href="https://github.com/StrangeDaysTech/straymark/pull/62" target="_blank" rel="noopener noreferrer" class="">#62</a> · <a href="https://github.com/StrangeDaysTech/straymark/pull/63" target="_blank" rel="noopener noreferrer" class="">#63</a> — refinamientos <code>cli-3.5.0</code> a <code>cli-3.5.2</code> (25-26 abr 2026). Código: <code>cli/src/tui/</code> (15 archivos). Doc adopter: <code>docs/adopters/CLI-REFERENCE.md</code> §<code>straymark explore</code>.</em></p>
<p><em>Este documento fue elaborado con asistencia de herramientas de IA generativa (Claude 4.7); toda la responsabilidad del contenido recae en el autor humano.</em></p>]]></content:encoded>
            <category>straymark</category>
            <category>tui</category>
            <category>cli</category>
            <category>i18n</category>
            <category>visibilidad-estructural</category>
        </item>
        <item>
            <title><![CDATA[Cuatro nombres en cuatro meses]]></title>
            <link>https://straymark.dev/es/blog/four-names-in-four-months</link>
            <guid>https://straymark.dev/es/blog/four-names-in-four-months</guid>
            <pubDate>Sun, 05 Apr 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[Buscar el concepto buscando el nombre]]></description>
            <content:encoded><![CDATA[<p><em>Chronicle → Monimen → DevTrail → Strange Days Tech → StrayMark. El arco prehistórico de cuatro renames en cuatro meses — tres apresurados en enero y uno disciplinado en mayo. La idea no se movió; el nombre sí.</em></p>
<!-- -->
<blockquote>
<p><strong>Nota editorial</strong>: este es el primer post publicado de forma retroactiva en el blog. La <code>date</code> del frontmatter corresponde a un momento dentro del arco que el post narra, no al día en que se escribió. El blog completo se está construyendo así, hacia atrás, desde el episodio que motivó empezar a escribirlo (<code>emergent-observation-design</code>, 2026-05-16). No tiene sentido fingir lo contrario.</p>
</blockquote>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="1-el-día-siguiente">1. El día siguiente<a href="https://straymark.dev/es/blog/four-names-in-four-months#1-el-d%C3%ADa-siguiente" class="hash-link" aria-label="Enlace directo al 1. El día siguiente" title="Enlace directo al 1. El día siguiente" translate="no">​</a></h2>
<p>El 28 de enero de 2026, a las 17:29 hora del centro, este commit entró al repo:</p>
<blockquote>
<p><code>chore: rebrand Chronicle to Monimen</code></p>
</blockquote>
<p>Un día. Veintinueve horas, para ser exacto, después del <em>initial commit</em> del proyecto. El framework apenas existía y ya estaba cambiando de nombre.</p>
<p>Lo cuento en pasado, pero esto pasó hace tres meses. Y hace tres meses, dos cambios de nombre después, todavía no se llamaba StrayMark. El proyecto que hoy se vende como <em>Documentation Governance for AI-Assisted Software Development</em> arrastra una prehistoria corta y desordenada que vale la pena nombrar antes de seguir adelante.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="2-cinco-eventos-cuatro-meses">2. Cinco eventos, cuatro meses<a href="https://straymark.dev/es/blog/four-names-in-four-months#2-cinco-eventos-cuatro-meses" class="hash-link" aria-label="Enlace directo al 2. Cinco eventos, cuatro meses" title="Enlace directo al 2. Cinco eventos, cuatro meses" translate="no">​</a></h2>









































<table><thead><tr><th>Fecha (UTC-6)</th><th>Hora</th><th>Evento</th><th>Ancla</th></tr></thead><tbody><tr><td>2026-01-27</td><td>12:14</td><td><em>Initial commit</em>: <strong>Enigmora Chronicle Framework v1.0.0</strong></td><td><a href="https://github.com/StrangeDaysTech/straymark/commit/7c58b6d" target="_blank" rel="noopener noreferrer" class=""><code>7c58b6d</code></a></td></tr><tr><td>2026-01-28</td><td>17:29</td><td>Rebrand: Chronicle → <strong>Monimen</strong></td><td><a href="https://github.com/StrangeDaysTech/straymark/commit/0b772bc" target="_blank" rel="noopener noreferrer" class=""><code>0b772bc</code></a></td></tr><tr><td>2026-01-29</td><td>19:30</td><td>Rebrand: Monimen → <strong>DevTrail</strong> (<code>BREAKING CHANGE</code>)</td><td><a href="https://github.com/StrangeDaysTech/straymark/commit/25ab7a4" target="_blank" rel="noopener noreferrer" class=""><code>25ab7a4</code></a></td></tr><tr><td>2026-03-01</td><td>19:05</td><td>Rebrand de la organización: Enigmora → <strong>Strange Days Tech</strong> + nace el CLI Rust</td><td><a href="https://github.com/StrangeDaysTech/straymark/commit/c7e9026" target="_blank" rel="noopener noreferrer" class=""><code>c7e9026</code></a></td></tr><tr><td>2026-05-08/09</td><td>—</td><td>DevTrail → <strong>StrayMark</strong> (ADR + arco de 5 PRs)</td><td>ADR <code>2026-05-08-001</code>, PRs #114-#118</td></tr></tbody></table>
<p>Tres renames en tres días. Después una pausa de un mes entero. Después el rebrand de la organización con CLI Rust incluido. Después otra pausa de dos meses. Después StrayMark, esta vez con ADR público anclando la decisión.</p>
<p>Detalle que me parece honesto subrayar: el commit del 28 de enero (Chronicle → Monimen) no se marcó como <code>BREAKING CHANGE</code>. El del 29 de enero (Monimen → DevTrail) sí. <em>"BREAKING CHANGE: Complete rebrand from Monimen to DevTrail"</em>, dice el body del commit. La diferencia es pequeña pero reveladora: el segundo rename se sintió más definitivo. Lo fue por dos meses.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="3-lo-que-no-se-mueve">3. Lo que no se mueve<a href="https://straymark.dev/es/blog/four-names-in-four-months#3-lo-que-no-se-mueve" class="hash-link" aria-label="Enlace directo al 3. Lo que no se mueve" title="Enlace directo al 3. Lo que no se mueve" translate="no">​</a></h2>
<p>Esta es la sección que me interesa más. El proyecto cambia cuatro veces de nombre en cuatro meses. La idea, no.</p>
<p>El README del <em>initial commit</em> — el que vivía en el repo cuando se llamaba <em>Enigmora Chronicle Framework</em> — abre con esta línea:</p>
<blockquote>
<p><strong>Documentation Governance for AI-Assisted Software Development</strong></p>
</blockquote>
<p>Es la misma línea que abre el README de StrayMark hoy. Cuatro nombres, un slogan.</p>
<p>Más adentro, el mismo README v1.0.0 enuncia la tesis del proyecto en un bloque de cita explícito:</p>
<blockquote>
<p><em>"No significant change without a documented trace."</em></p>
</blockquote>
<p>Esa frase, hoy, es el Principio #1 del framework. Está en <code>PRINCIPLES.md §1 — Total Traceability</code>. La redacción cambió ligeramente al traducirse al español, pero el peso de la afirmación quedó intacto: ningún cambio significativo sin rastro documentado.</p>
<p>Los ocho tipos de documento que listaba el README v1.0.0 — REQ, ADR, TES, INC, TDE, AILOG, AIDEC, ETH — siguen vivos. Después se agregaron otros (MCARD, SBOM, SEC, DPIA), pero ninguno desplazó a los originales. La taxonomía de enero se sostuvo.</p>
<p><strong>El nombre se mueve cuatro veces, la idea no.</strong> Lo que cambió en esos cuatro meses no fue el qué, sino la etiqueta que servía para nombrarlo.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="4-el-aidec-con-año-tipográfico">4. El AIDEC con año tipográfico<a href="https://straymark.dev/es/blog/four-names-in-four-months#4-el-aidec-con-a%C3%B1o-tipogr%C3%A1fico" class="hash-link" aria-label="Enlace directo al 4. El AIDEC con año tipográfico" title="Enlace directo al 4. El AIDEC con año tipográfico" translate="no">​</a></h2>
<p>Hay una anécdota pequeña que me sigue gustando.</p>
<p>El primer documento estructurado del proyecto — el primer AIDEC, el documento que en la propia taxonomía del framework registra una decisión tomada con asistencia de un agente — es <code>AIDEC-2025-01-27-001-i18n-strategy.md</code>. Está en el commit <a href="https://github.com/StrangeDaysTech/straymark/commit/7b7193e" target="_blank" rel="noopener noreferrer" class=""><code>7b7193e</code></a>, agregado a las 18:01 del 27 de enero de 2026, seis horas después del <em>initial commit</em>.</p>
<p>El ID dice <strong>2025</strong>. El commit es de <strong>2026</strong>.</p>
<p>El propio documento que sentó la convención de identificadores tipo <code>[TYPE]-[YYYY-MM-DD]-[NNN]</code> tiene un error tipográfico en el año. El framework arrancó imperfecto y nadie lo corrigió a tiempo. Si alguien clona el repo y mira al ID de ese AIDEC con cuidado, lo notará — y verá también que el commit que lo introdujo está fechado correctamente. Es la mejor evidencia que tengo de que la disciplina de auditoría es algo que llega después; no nace con el repo.</p>
<p>Pero más interesante que el error es lo que decide ese AIDEC. La pregunta que se planteó José en enero, con asistencia de Claude Opus 4.5, era: ¿cómo internacionalizamos un framework que existe para los humanos pero cuya configuración la leen agentes? La respuesta, en la sección de justificación del propio AIDEC:</p>
<blockquote>
<p><em>"AI agents (Claude, Gemini, Copilot, Cursor) process instructions equally well in any language, so translating their config files provides no functional benefit."</em></p>
</blockquote>
<p>La decisión que tomó ese documento — traducir lo que leen humanos (documentación, plantillas), mantener en inglés lo que leen agentes (CLAUDE.md, GEMINI.md, .cursorrules) — fue una intuición temprana sobre que el framework tiene dos audiencias distintas. Hoy el blog mismo ratifica esa intuición: bilingüe español/inglés para los humanos que lo lean, mientras las skills y prompts que orquestan agentes siguen viviendo solo en inglés. Tres meses después, sigue siendo la decisión correcta.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="5-el-nacimiento-del-cli--y-el-número-que-faltó">5. El nacimiento del CLI — y el número que faltó<a href="https://straymark.dev/es/blog/four-names-in-four-months#5-el-nacimiento-del-cli--y-el-n%C3%BAmero-que-falt%C3%B3" class="hash-link" aria-label="Enlace directo al 5. El nacimiento del CLI — y el número que faltó" title="Enlace directo al 5. El nacimiento del CLI — y el número que faltó" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="5a-el-día-que-el-proyecto-se-volvió-software">5a. El día que el proyecto se volvió software<a href="https://straymark.dev/es/blog/four-names-in-four-months#5a-el-d%C3%ADa-que-el-proyecto-se-volvi%C3%B3-software" class="hash-link" aria-label="Enlace directo al 5a. El día que el proyecto se volvió software" title="Enlace directo al 5a. El día que el proyecto se volvió software" translate="no">​</a></h3>
<p>El 1 de marzo de 2026, a las 19:05, entró el commit <a href="https://github.com/StrangeDaysTech/straymark/commit/c7e9026" target="_blank" rel="noopener noreferrer" class=""><code>c7e9026</code></a>:</p>
<blockquote>
<p><em>"feat: rebrand to Strange Days Tech, add CLI scaffolder, restructure repo"</em></p>
</blockquote>
<p>Hasta ese día, el proyecto era prosa. Eran templates, skills, reglas de gobernanza, y un montón de Markdown que dependía de que el operador (yo) los copiara a mano dentro de los repos donde quería usarlos. Había un script bash llamado <code>copy-devtrail.sh</code>. Era de juguete.</p>
<p>Ese commit del 1 de marzo introdujo <code>cli/Cargo.toml</code> y <code>cli/src/main.rs</code>. El primer CLI se llamó <code>devtrail-cli</code>, versión <code>2.0.0</code>, y tenía tres comandos:</p>
<div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">enum</span><span class="token plain"> </span><span class="token type-definition class-name">Commands</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token class-name">Init</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> path</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token class-name">String</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token class-name">Update</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token class-name">Remove</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> full</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">bool</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></div></code></pre></div></div>
<p><code>init</code>, <code>update</code>, <code>remove</code>. Tres operaciones. El resto vino después: <code>status</code>, <code>repair</code>, <code>validate</code>, <code>new</code>, <code>compliance</code>, <code>metrics</code>, <code>analyze</code>, <code>audit</code>, <code>explore</code>. Pero los tres originales siguen ahí, casi sin tocar.</p>
<p>Lo importante del commit no son los tres comandos: es que ese día el proyecto dejó de ser un cuerpo de documentación que vivía en su propio repo y empezó a ser una herramienta ejecutable que se instalaba en otros repos. La frontera entre <em>"proyecto de gobernanza documental"</em> y <em>"framework con tooling"</em> se cruzó ese domingo de marzo. Es más importante que cualquiera de los renames que vinieron antes.</p>
<p>Es también, por cierto, el día en que el proyecto se mudó de cuenta en GitHub: de <code>enigmora/devtrail</code> a <code>StrangeDaysTech/devtrail</code>. La organización pasó de llamarse Enigmora a Strange Days Tech, S.A.S., en el mismo commit que estrenó el CLI. Renames simultáneos: el del producto (de Monimen a DevTrail) había ocurrido en enero; el de la empresa, en marzo. Dos capas separadas de identidad moviéndose en distintos relojes.</p>
<p>(Una nota lateral, importante para el cuidado del archivo: la co-autoría con un agente — ese <code>Co-Authored-By: Claude Opus X.Y</code> que aparece en commits — no nace en marzo. El <em>initial commit</em> del 27 de enero ya viene firmado por Claude Opus 4.5. La transparencia de co-autoría con IA fue regla desde la primera línea de código. Lo que cambia el 1 de marzo no es la práctica, es la escala: el CLI es el primer artefacto donde la co-autoría produce <em>código ejecutable</em>, no documentación.)</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="5b-el-número-que-faltó">5b. El número que faltó<a href="https://straymark.dev/es/blog/four-names-in-four-months#5b-el-n%C3%BAmero-que-falt%C3%B3" class="hash-link" aria-label="Enlace directo al 5b. El número que faltó" title="Enlace directo al 5b. El número que faltó" translate="no">​</a></h3>
<p>Hay un detalle del versionado del framework que se entiende mejor mirando <code>git tag</code>:</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">fw-2.0.0</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">fw-2.1.0</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">fw-4.0.0</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">fw-4.1.0</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">...</span><br></div></code></pre></div></div>
<p>No hay <code>fw-3.x.x</code>. El proyecto saltó deliberadamente del 2 al 4.</p>
<p>El salto se sincroniza con el commit <a href="https://github.com/StrangeDaysTech/straymark/commit/21e03b2" target="_blank" rel="noopener noreferrer" class=""><code>21e03b2</code></a>, del 27 de marzo de 2026, cuyo cuerpo describe el cambio así:</p>
<blockquote>
<p><em>"Reposition DevTrail from 'documentation helper' to 'ISO 42001-aligned AI governance platform' across all user-facing docs. Lead with regulatory urgency (EU AI Act Aug 2026) and compliance value proposition."</em></p>
</blockquote>
<p>Hasta marzo, DevTrail se presentaba como <em>ayudante de documentación</em>. A partir de ese commit, se presentó como <em>plataforma de gobernanza de IA alineada con ISO 42001</em>. El cambio de número (2 → 4, saltando el 3) marcó la magnitud del cambio de tesis. Fue una decisión consciente: una versión mayor no alcanzaba para señalar la diferencia.</p>
<p>Y aquí es donde la prehistoria empieza a tener sentido retrospectivo. La intuición que estuvo en el repo desde enero — la idea de un sistema de registro robusto, normativo, alineable con estándares de gobernanza — solo se nombró explícitamente en marzo. Lo veremos con más claridad en la próxima sección, al hablar del segundo nombre.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="6-sobre-los-nombres">6. Sobre los nombres<a href="https://straymark.dev/es/blog/four-names-in-four-months#6-sobre-los-nombres" class="hash-link" aria-label="Enlace directo al 6. Sobre los nombres" title="Enlace directo al 6. Sobre los nombres" translate="no">​</a></h2>
<p>Tres de los cuatro renames no tienen ADR. La justificación vive solo en los commit messages, y a veces ni siquiera ahí: el commit <code>chore: rebrand Chronicle to Monimen</code> no dice por qué Monimen. El siguiente, <code>chore: rebrand Monimen to DevTrail</code>, tampoco dice por qué DevTrail. La práctica del ADR como artefacto disciplinado llegó después; en enero el nombre cambiaba con un commit y la justificación se evaporaba en la conversación que la había producido.</p>
<p>Pero algo de etimología sí podemos rescatar.</p>
<ul>
<li class="">
<p><strong>Chronicle</strong> <em>(27 ene)</em>. Registro histórico. Bitácora. El nombre habla por sí: lo que se hace con un <em>chronicle</em> es anotar lo que sucedió, en orden, para que se pueda revisar después. No hay ADR pero la palabra carga su propio sentido.</p>
</li>
<li class="">
<p><strong>Monimen</strong> <em>(28 ene)</em>. Este es el único nombre cuya intuición sí recuerdo y vale contar. <em>Monimen</em> surgió como juego de palabras a partir de <em>Monumento</em> (Monument en inglés). La analogía que motivó la sugerencia: las normas que ya entonces se intuían — AIDEC, AILOG, alineables con la incipiente normativa ISO 42001 — representaban una estructura sólida, duradera. Un <em>monumento</em> es algo que se erige para durar; un pilar de referencia inamovible para una comunidad. Eso quería ser el framework. El sufijo cortado — <em>Monimen</em> en vez de <em>Monument</em> — buscaba darle al término un toque más ágil, más de software, menos de mármol. Duró 25 horas. Pero la intuición no se perdió: lo que en marzo terminó nombrándose explícitamente como <em>ISO 42001-aligned AI governance platform</em> es la versión madura de ese mismo impulso. Monimen era un nombre con la tesis correcta y la lengua equivocada.</p>
</li>
<li class="">
<p><strong>DevTrail</strong> <em>(29 ene)</em>. El recorrido del developer. Menos solemne que Monimen, más concreto. El commit lo marcó <code>BREAKING CHANGE</code> — lo cual, mirado desde mayo, tiene una ironía: el rebrand más definitivo de los primeros tres fue precisamente el que duró tres meses y medio antes de ser sustituido.</p>
</li>
<li class="">
<p><strong>StrayMark</strong> <em>(8-9 may)</em>. La marca, la seña que queda. Pero ese rebrand pide su propio post: ya hay ADR público (<code>2026-05-08-001</code>), un arco de cinco PRs nucleares (#114-#118), y un manifesto <em>"Why StrayMark?"</em> en el README que merece tratamiento aparte. Aquí solo lo cierro como el rebrand que vino con disciplina documental detrás.</p>
</li>
</ul>
<p>Lo importante no es la etimología en sí. Es que cada nombre ratifica una intuición distinta sobre qué es el producto: <strong>bitácora</strong> (Chronicle), <strong>pilar normativo</strong> (Monimen), <strong>recorrido del developer</strong> (DevTrail), <strong>marca residual</strong> (StrayMark). Cuatro nombres son cuatro hipótesis sobre el concepto. La búsqueda termina cuando el concepto se estabiliza — y solo entonces el nombre puede quedarse quieto.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="7-cierre">7. Cierre<a href="https://straymark.dev/es/blog/four-names-in-four-months#7-cierre" class="hash-link" aria-label="Enlace directo al 7. Cierre" title="Enlace directo al 7. Cierre" translate="no">​</a></h2>
<p>Lo que aprendí del proceso, en cuatro tesis:</p>
<ol>
<li class="">
<p><strong>No buscábamos un nombre. Buscábamos al concepto.</strong> Los cuatro renames son evidencia de búsqueda, no de indecisión. El concepto se fue afilando a través de los nombres que probaba.</p>
</li>
<li class="">
<p><strong>Tres de cuatro renames sin ADR.</strong> La práctica del ADR como artefacto disciplinado llegó después. En enero todavía no había hábito. Eso no es deuda: es honestidad sobre el ritmo. Los hábitos de gobernanza son el resultado de querer registrar lo que ya estaba pasando, no la precondición para empezar.</p>
</li>
<li class="">
<p><strong>El proyecto se volvió software el 1 de marzo de 2026. Antes, era prosa.</strong> El CLI Rust es la frontera. Cualquier discusión sobre StrayMark <em>como framework</em> tiene que reconocer que hay un antes y un después de ese commit.</p>
</li>
<li class="">
<p><strong>Probablemente no vuelva a haber rebranding.</strong> Pero el blog no lo promete. El proyecto es honesto sobre su propia mutabilidad, y prometerlo sería traicionar la primera tesis del primer post.</p>
</li>
</ol>
<p>Cuando empecé a escribir este blog, hace dos semanas, no tenía intención de cubrir la prehistoria. La idea era hablar de Charters, de observación emergente, de las cosas que el framework hoy hace. Pero el blog mismo es un acto retroactivo — nace porque algo me sorprendió lo suficiente como para empezar a escribir. Y una vez que decidí escribir hacia atrás, fue inevitable llegar a enero. A los tres renames en tres días. Al AIDEC con año tipográfico. A <em>Monimen</em>.</p>
<p>Sigue, en el siguiente post, el primer experimento metodológico real del framework: los seis Planes de Sentinel y el día que <em>Plan</em> se renombró a <em>Charter</em>. Ahí empieza la historia que el blog vino a contar.</p>
<hr>
<p><em>Anclas: commits <a href="https://github.com/StrangeDaysTech/straymark/commit/7c58b6d" target="_blank" rel="noopener noreferrer" class=""><code>7c58b6d</code></a> · <a href="https://github.com/StrangeDaysTech/straymark/commit/0b772bc" target="_blank" rel="noopener noreferrer" class=""><code>0b772bc</code></a> · <a href="https://github.com/StrangeDaysTech/straymark/commit/25ab7a4" target="_blank" rel="noopener noreferrer" class=""><code>25ab7a4</code></a> · <a href="https://github.com/StrangeDaysTech/straymark/commit/7b7193e" target="_blank" rel="noopener noreferrer" class=""><code>7b7193e</code></a> · <a href="https://github.com/StrangeDaysTech/straymark/commit/c7e9026" target="_blank" rel="noopener noreferrer" class=""><code>c7e9026</code></a> · <a href="https://github.com/StrangeDaysTech/straymark/commit/21e03b2" target="_blank" rel="noopener noreferrer" class=""><code>21e03b2</code></a>. README original: <code>git show v1.0.0:README.md</code>.</em></p>
<p><em>Este documento fue elaborado con asistencia de herramientas de IA generativa (Claude 4.7); toda la responsabilidad del contenido recae en el autor humano.</em></p>]]></content:encoded>
            <category>straymark</category>
            <category>prehistoria</category>
            <category>identidad</category>
            <category>governance</category>
        </item>
    </channel>
</rss>