Tech Lead's Club - Spec, Lean
Congela las obligaciones. Libera el plan. Pruébalo con alguien que no lo construyó. Derivado de tlc-spec-driven 3.3.0 (Felipe Rodrigues), tlc-plan y tlc-implement.
┌──────┐ ┌────────┐ ┌───────┐ ┌────────┐
│ PLAN │ → │ CHECKS │ → │ BUILD │ → │ VERIFY │
└──────┘ └────────┘ └───────┘ └────────┘
léelo obligaciones tuyo siempre
Cuatro movimientos, dos artefactos antes del código, uno después. Un humano confirma qué debe ser verdad y cómo se está construyendo en un documento, y solo entonces algo se convierte en una obligación con una prueba adjunta. No hay desglose de tareas, y el plan no lleva un catálogo de componentes: lo que es difícil de revertir obtiene una puerta unidireccional con su forma literal, y todo lo reversible se decide mientras se construye y se revisa en el diff.
Por qué esta forma
El fracaso dominante de un agente de codificación no es el mal razonamiento, es un requisito que se leyó y nunca se convirtió en una obligación activa, y luego un reclamo de finalización sobre eso. La mitigación que se mide bien es un conjunto pequeño, congelado y externo de obligaciones más un verificador que no es el autor; una auto-verificación reproduce el punto ciego del autor. Por lo tanto, esta habilidad gasta su presupuesto en esas dos cosas y se niega a gastarlo en coreografiar cómo trabaja el modelo.
Dos consecuencias que vale la pena mencionar de antemano, porque son lo que hace que esto sea diferente de un flujo convencional impulsado por especificaciones:
- La granularidad no es calidad. Dividir una funcionalidad en quince tareas de un archivo compra orden, no corrección, y cuesta releer el proceso en cada tarea. La cobertura de pruebas compra corrección.
- Un plan que el modelo debe obedecer compite con las obligaciones por la atención. Campos como
Dónde,Herramientas,Depende deson decisión del modelo, por lo que no se escriben.
Reglas críticas
El conjunto fijo. Estas se mantienen incluso si no se lee ningún archivo de referencia, y son las únicas reglas que nunca se reducen con el perfil.
- Cada verificación es una afirmación observable con un valor concreto más la prueba - la prueba o comando cuyo código de salida la resuelve. Sin prueba, no hay verificación.
- Las pruebas afirman lo que dicen las verificaciones, nunca lo que el código hace. Nunca escribas una prueba leyendo la implementación.
- Nunca debilites una afirmación, elimines una prueba o te saltes una para que una suite pase. Una verificación genuinamente incorrecta es una parada y pregunta, no una edición.
- Las verificaciones y las filas de
Política de pruebasson fijas una vez aprobadas. En el diseño,Aterrizaje,RelacionesySuperficieson aditivos: una puerta descubierta durante la construcción obtiene una fila antes del código que la cierra, y una fila que el usuario aprobó nunca se reescribe.FlujoeImpactono lo son: se mantienen verdaderos, por lo que un camino diferente cambia el salto en el commit de ese camino. - El Verificador es un sub-agente nuevo, nunca el autor, nunca opcional, nunca esperando
a que se le pregunte. Quien tenga toda la funcionalidad lo envía después del último commit de la
funcionalidad - sobre
<base de funcionalidad>..HEAD, con cada verificación. Nunca por un constructor, y nunca como hijo de uno. Un constructor termina, informa y se detiene. El trabajo no está terminado en el último commit; está terminado cuando el informe del Verificador da cuenta de cada verificación. - El perfil es un piso y no es un secreto. El informe de verificación lo nombra, o "sin fallos inyectados" se lee exactamente como olvidar inyectarlos.
- La puerta de finalización es un script, no una sensación:
validate_verification.pydebe salir con 0. - Radio de explosión: una especificación aprobada autoriza ediciones locales y commits locales.
git push, despliegue y cambios en datos de producción necesitan una autorización explícita para esa acción.
Perfil
El proyecto declara cuánto se ejecuta, en AGENTS.md o equivalente. A falta de declaración:
light. Los mismos tres niveles que tlc-implement, controlados de la misma manera, por lo que moverse entre las dos
habilidades no necesita un segundo vocabulario.
## tlc-spec-lean
profile: light
budget: 150k
| Perfil | Añade | No puede detectar |
|---|---|---|
light (predeterminado) | las pruebas se ejecutan en HEAD con cada prueba nombrada mostrada como existente y ejecutada, una afirmación ubicada por verificación, nivel y brechas de muestreo, Barrido existente releído | un miembro del conjunto sin prueba; una prueba que pasaría bajo una implementación incorrecta |
standard | la unión de Cobertura recalculada, filas de Política de pruebas con un veredicto cada una, un fallo por superficie de afirmación | una verificación que contradice una fuente vinculante; una pantalla que nadie construyó |
ui | fuentes vinculantes abiertas y comparadas, enumeración por pantalla de copia y disposición | solo espaciado, color y peso de tipo, enumerado por pantalla |
Cada paso añade una clase de fallo detectado, por lo que un perfil barato no es un descuento en el
mismo producto: lea la columna derecha antes de elegirlo. Dos cosas sobre light vale la pena decir
en voz alta, porque su propia fila las dice y son fáciles de pasar por alto: no notará
un miembro del conjunto enumerado que nadie probó, y no notará una prueba que pasa bajo
una implementación incorrecta. standard existe exactamente para esos dos.
ui no cuesta nada en trabajo sin interfaz: cada paso de pantalla está condicionado a que exista una
pantalla. Un paso cuya entrada está vacía cuesta una línea, no una pasada ("sin filas de conjunto", "sin
fuente vinculante").
La unión de Cobertura se escribe en checks.md en cada perfil: la unión es lo que hace que una
omisión sea estructural, y eso no cuesta nada en el momento de la autoría. Lo que standard compra es que el
Verificador la recalcule a partir de la autoridad sobre cada conjunto en lugar de leer la
tabla del autor.
El perfil es un pin, no una preferencia, y a diferencia de tlc-implement que se solicita en lugar de
exigirse: validate_verification.py falla un informe cuyo perfil difiere del que
checks.md fue aprobado, y falla un informe standard sin filas de fallo o sin
cobertura recalculada, y un informe ui sin una sección de fuentes vinculantes. Por lo que un paso que no
se ejecutó sigue siendo distinguible de un paso que se olvidó, que es la razón completa para declarar
un piso.
Cuando el perfil parezca demasiado ligero para la funcionalidad en cuestión, dígalo en una línea y deje que el usuario lo eleve. Hacer más que el perfil en silencio cuesta la previsibilidad que hizo que declararlo valiera la pena.
Artefactos
.specs/
├── STATE.md # Registro de decisiones (AD-NNN) + Instantánea de transferencia
├── LESSONS.md # renderizado por scripts/lessons.py - nunca editar a mano
├── lessons.json # propiedad de la máquina
└── features/<feature>/
├── plan.md # problema, flujo, impacto, luego el resto de la forma, luego criterios; auditoría al final
├── checks.md # afirmaciones + pruebas, la unión de cobertura, política de pruebas, barrido
└── verification.md # informe del Verificador
Cree cada archivo cuando su fase produzca contenido. Para un cambio de aproximadamente tres archivos sin
puerta unidireccional, escriba solo checks.md con un párrafo ## Intención y omita plan.md - una
salida acotada, no una matriz de tamaño.
La comprensión y las obligaciones son artefactos separados
plan.md existe porque un humano tiene que poder planificar y objetar antes de que cualquier cosa se convierta en
una afirmación con un selector de prueba adjunto. Leer cuarenta verificaciones para reconstruir lo que se está construyendo no
es planificar, y escribir las verificaciones en la misma pasada que decide la forma produce verificaciones que
ratifican lo que ya se suponía.
Ambas mitades viven en un archivo porque son una revisión. El límite del archivo es semántico:
de este lado, lo que un humano confirma; del otro, obligaciones con pruebas. Dividir el
plan en una especificación y un diseño lo cortaría en un lugar que no coincide con ninguno, y compraría dos
paradas obligatorias para una funcionalidad. El orden del archivo es para leer: Problema, Flujo, Impacto, luego
el resto de la forma, luego los criterios, luego las tablas de auditoría. El orden de escritura no lo es: escriba el
problema, recorra las superficies, escriba los criterios, luego complete la forma. Eso es lo que evita
que se invente un criterio para justificar un componente. La puerta de cierre aún requiere que cada
criterio aterrice en algún lugar de Flujo, Relaciones o Superficie, o está fuera de alcance o es una
brecha en la forma.
La derivación a checks.md es la parte que soporta la carga, no el papeleo. Cada ruta en Superficie
debe una fila de conjunto de Cobertura cuyos miembros son sus estados; cada puerta en Aterrizaje debe una verificación;
cada entidad en Relaciones debe una. Una sección de forma sin nada que apunte de vuelta desde
checks.md está muerta o no probada, y validate_checks.py advierte sobre el caso común.
La mitad del diseño existe; el catálogo de componentes no. Lo que hizo que los documentos de diseño se pudrieran nunca
fue el diagrama, fue Propósito / Ubicación / Interfaces / Dependencias por clase -
detalle reversible que se vuelve obsoleto en semanas y luego engaña al próximo lector con la
autoridad de un documento escrito. Ninguno de esos campos existe aquí. Cinco secciones acotadas:
| Sección | Revisa | Mantiene fuera |
|---|---|---|
Flujo | la ruta, una línea por salto | cualquier módulo que ni existe ni es creado por una puerta - eso es colocación |
Impacto | qué cambia por debajo: términos y datos existentes | registros de riesgo |
Relaciones | entidades, cardinalidad, restricciones unidireccionales | columnas y tipos |
Superficie | ruta, entrada, salida, estados | especificación del cuerpo de la solicitud e IDs de verificación - esos aún no existen |
Aterrizaje | las puertas unidireccionales, con la forma literal y la alternativa rechazada | cualquier cosa que un refactor revierta |
Qué carpeta, cuántas clases, cómo se llama el método privado: el diff. Reversible, respondido por las convenciones del repositorio, y nunca vale un artefacto. Ese es el equilibrio deliberado, y es el único.
Una apuesta aún abierta cuando llegue aquí - dos arquitecturas con alternativas vivas, cada una necesita ser
costeada contra este repositorio - no encaja en una fila de Aterrizaje, y una fila es la única forma que este
artefacto tiene para ello. Lo que sea que el proyecto use para resolver uno (un ADR, un RFC, un spike) viene
primero; luego el plan registra la forma que ganó y la hace revisable.
Flujo
Plan - el problema, luego la ruta y lo que el cambio perturba, luego el resto de la forma,
luego los criterios. La escritura aún va: problema → superficies → criterios → forma. Hechos que
investigas; decisiones que preguntas - y cuando preguntas, opciones concretas con tu recomendación, como máximo dos
por turno. Dos enumeraciones hacen el hallazgo, porque "considera los casos límite" no encuentra nada: las
superficies que esta funcionalidad expone, cada una con las mismas decisiones cada vez que aparece, y las nueve
dimensiones de requisitos implícitos. Ambas toman un n/a - <razón> obligatorio, por lo que un espacio en blanco es un elemento
que nadie decidió en lugar de uno que no aplica. Un artefacto que un humano lee y objeta
antes de que exista cualquier verificación. Proceso completo, cómo preguntar, reglas por sección de forma, plantilla y puerta
de cierre: plan.md.
Checks - deriva afirmaciones con pruebas del plan, une cada miembro del conjunto enumerado a una verificación,
y registra dónde aterrizó cada dimensión barrida. Cierra con ## Handoff y la aritmética; si
la estimación excede el presupuesto, detente para preguntar por el mecanismo antes de Build. Este es el artefacto al que
todo lo posterior se refiere por número de verificación: checks.md.
Build - tu decisión cómo, después de la aritmética de ## Handoff y, si la estimación excede el
presupuesto, la elección de mecanismo del usuario. Escribe las pruebas a partir de las verificaciones, implementa, ejecuta cada
prueba, haz commit en piezas coherentes. Sin lista de tareas, sin tablas de revisión por tarea. Límites,
temporización de Aterrizaje, transferencia y la barandilla de alcance: build.md.
Verify - cuando el último commit de la funcionalidad aterrice, envía un Verificador nuevo en el mismo turno. No preguntes. No esperes a "verificar trabajo". Procedimiento, formato del informe y re-verificación con alcance: verify.md.
Memoria duradera - decisiones del proyecto, transferencia de sesión y la capa de lecciones: memory.md.
Scripts
Resuelve <skill-dir> como el directorio que contiene este SKILL.md e invoca
python3 <skill-dir>/scripts/<name>.py. Los datos del proyecto bajo .specs/ permanecen relativos a la
raíz del proyecto; pasa --root cuando el directorio de trabajo actual difiera. Un código de salida no cero significa STOP y arregla.
| Cuándo | Comando |
|---|---|
| Antes de presentar el plan | validate_plan.py <feature> |
| Antes de empezar a construir | validate_checks.py <feature> |
| Antes de cada commit | check_commit.py --message "<msg>" |
| Antes de declarar terminado | validate_verification.py <feature> |
| En la destilación | lessons.py add ... |
| Después de editar un validador o plantilla | selftest.py |
validate_plan.py ejecuta la puerta de cierre y protege la mitad de la forma de convertirse en lo que
reemplazó: falla un criterio sin DEBE, una suposición sin un valor predeterminado elegido, una fila Observable
cuyo aterrizaje está en blanco o cuyo n/a no lleva razón, una fila Aterrizaje
sin forma literal o sin alternativa rechazada, columnas y tipos dentro de Relaciones, una
ruta de Superficie sin estados, y cualquier sección dejada en blanco en lugar de respondida con
None - <por qué>. validate_checks.py es el capturador de omisiones: falla una verificación sin prueba, una
fila de cobertura cuyo tamaño declarado excede los miembros realmente asignados, una dimensión barrida faltante
y una línea de perfil faltante, y advierte sobre una ruta que el plan revisó y que ninguna verificación menciona.
validate_verification.py falla un informe PASS que no cita ningún file:line, registra un
mutante sobreviviente, deja un miembro Unproven, o fue escrito por el autor.
Omite un script solo cuando no exista ninguna herramienta de ejecución de código; luego realiza las mismas comprobaciones leyendo el artefacto y di una vez en el chat que estás en la ruta degradada.
selftest.py aplica la propia disciplina de esta habilidad a sus puertas: muta un conjunto de
fixtures rellenado una vez por regla y requiere que cada mutante sea eliminado, ejecuta controles negativos que demuestran que una puerta
con ámbito de perfil no se dispara por debajo de su perfil, y ejecuta una prueba de humo para cada script enviado
aquí - un script sin ejercitar es donde se esconde un fallo, y la puerta de finalización una vez salió con 0 con n
...[truncado para traducción]