test-driven-development (obra/superpowers)
Implementa funciones y correcciones con test-first, escribiendo primero la prueba que falla.
superpowers test-driven-development: hace que el agente escriba primero el test, y cuesta alrededor de 1.6 veces los tokens
Codex CLI · gpt-6-astra
24.0 / 30
Mejora frente a sin skill: +1.00 · Recomendada · 18 ejecuciones
Recomendada: el total 24.0/30 es al menos 22, la calidad de salida 5.0 es al menos 3.5 y la mejora +1.00 es al menos +1.0.
SOTA
AprobadaProbada con Codex.
Cubre Codex, Claude Code
Codex CLI 0.166 (nivel SOTA): 18 ejecuciones puntuadas. Una pasada aquí también cubre Claude Code según nuestra regla de niveles; no dice nada sobre el segundo nivel.
Puntuaciones
Cada dimensión va de 0 a 5 y las seis suman el total sobre 30. 5 es mejor en todas las dimensiones. Coste 5 significa barato y rápido. Instalación 5 significa fácil.
- Fiabilidad de activación
- 5.0
- Mejora frente a sin skill
- 3.0
- Calidad de salida
- 5.0
- Coste en tokens y tiempo
- 2.0
- Instalación y portabilidad
- 4.0
- Seguridad
- 5.0
Revisión de seguridad
SeguraEscaneo estático: 0 CRITICAL / 0 HIGH / 0 MEDIUM. Revisión manual: Segura de ejecutar en un sandbox sin red (sin hallazgos). Un escaneo limpio no demuestra que una skill sea segura.
Instalar
npx skills@latest add obra/superpowers --skill test-driven-development
Commit fijado: 2ce8aa15d05bd57213e6f746f953aafb7ded7a8b
Probada: 2026-11-02
Qué probamos
- Implementa una función a partir de una especificación precisa — Implementa slugify(text, max_length=None) en slug.py (Python 3, solo biblioteca estándar). Especificación: pasa el texto a minúsculas; sustituye cada secuencia de caracteres que no sean letras ASCII o dígitos por un único '-'; elimina los '-' iniciales y finales; un resultado vacío se convierte en 'n…
- Implementa una clase pequeña con estado — Escribe ratelimiter.py (Python 3, solo biblioteca estándar) con la clase RateLimiter(limit, window_seconds, clock=time.monotonic): un limitador de ventana deslizante por clave. allow(key) devuelve True y registra la llamada si se registraron menos de limit llamadas en los últimos…
- Corrige un bug de redondeo — Los clientes dicen que cart_total en cart.py a veces se desvía un céntimo respecto a nuestro sistema contable, que redondea los medios céntimos al alza en cada paso (el total de cada línea, el subtotal con descuento y los impuestos). Por ejemplo, cart_total([(1.005, 1)]) debería devolver 1.09 y…
Ventajas
- Eleva la puntuación media de 4.0 a 5.0 frente a sin skill (+1.00).
- La skill se activó sin nombrarla: se leyó el archivo de la skill en 6/6 ejecuciones con skill.
- Supera a una versión de su propia regla en una frase por +0.33.
- Calidad absoluta alta con la skill: 5.0 sobre 5.
Inconvenientes
- Usa 1.65 veces los tokens de sin skill.
- Salvedad de la prueba: la rama del prompt de una frase (6 ejecuciones) se añadió después en una máquina distinta de las ramas de control y con skill.
- n=2 por tarea y rama; las diferencias de menos de aproximadamente 1 punto son ruido.
Reseña
Codex CLI 0.166 (gpt-6-astra, razonamiento bajo) en una máquina de pruebas Mac, un proyecto temporal nuevo y HOME/TMPDIR/cachés temporales en cada ejecución, skill instalada (grupo con skill), ausente (control) o ausente con el requisito central de la skill comprimido en una frase añadida al prompt (grupo del prompt de una frase), 2 ejecuciones por grupo y tarea, red desactivada, escrituras en /tmp bloqueadas. Los prompts nunca mencionan la skill. La puntuación es programática (tests ocultos / recuerdo de problemas plantados / comprobaciones de restricciones / render+OCR cuando corresponde), 0–5 por ejecución. Ningún juez LLM decidió ninguna puntuación.
Comparación de tres ramas
| Rama | Puntuación media (0-5) | Tokens por ejecución |
|---|---|---|
| Sin la skill | 4.0 | 65k |
| Prompt de una frase | 4.67 | 127k |
| Con la skill | 5.0 | 108k |
Medido con Codex CLI en 18 ejecuciones, puntuado con comprobaciones basadas en reglas y sin juez LLM. Total 24.0 / 30, veredicto Recomendada.
Aviso: La rama de una frase (6 ejecuciones) se añadió más tarde en una máquina distinta de las ramas de control y con skill.
Veredicto: Recomendado (24.0 / 30). Fuente: obra/superpowers, skills/test-driven-development, fijado en el commit 2ce8aa1. Instalación: npx skills@latest add obra/superpowers --skill test-driven-development. Licencia: MIT (LICENSE del repositorio).
Qué es
El skill test-driven-development de obra/superpowers. Su descripción dice «úsalo al implementar cualquier funcionalidad o corrección de bug, antes de escribir el código de implementación». Unas 1,500 palabras de Markdown (la «ley de hierro» del rojo-verde-refactor, una tabla de excusas para saltarse el test, una lista de verificación) más un archivo adicional sobre cómo escribir buenos tests. Sin scripts.
Cómo lo probamos
Codex CLI 0.166 (gpt-6-astra, razonamiento bajo) en un Mac de pruebas, un proyecto temporal nuevo y HOME/TMPDIR/cachés temporales en cada ejecución, skill instalado (grupo con skill), ausente (grupo de control) o ausente con el requisito central del skill comprimido en una frase añadida al prompt (grupo de una frase), 2 ejecuciones por grupo y tarea, red desactivada, escrituras en /tmp bloqueadas. Los prompts nunca mencionan el skill.
- Implementar una función a partir de una especificación precisa — Implementa
slugify(text, max_length=None)en slug.py (Python 3, solo biblioteca estándar). Especificación: pasa el texto a minúsculas; sustituye cada secuencia de caracteres que no sean letras ASCII ni dígitos por un único '-'; elimina los '-' iniciales y finales; un resultado vacío se convierte en 'n… - Implementar una pequeña clase con estado — Escribe ratelimiter.py (Python 3, solo biblioteca estándar) con la clase
RateLimiter(limit, window_seconds, clock=time.monotonic): un limitador de ventana deslizante por clave.allow(key)devuelve True y registra la llamada si se registraron menos delimitllamadas en los últimos… - Corregir un bug de redondeo — Los clientes dicen que
cart_totalen cart.py a veces se desvía un céntimo respecto a nuestro sistema contable, que redondea al alza al céntimo en cada paso (el total de cada línea, el subtotal con descuento y los impuestos). Por ejemplo, cart_total([(1.005, 1)]) debería devolver 1.09 y…
La puntuación es programática (tests ocultos / detección de problemas sembrados / comprobaciones de restricciones / renderizado+OCR cuando corresponde), de 0 a 5 por ejecución. Ningún juez LLM decidió ninguna puntuación.
Resultados
La frase única que recibió el tercer grupo: "Sigue un rojo-verde-refactor estricto: escribe primero un test que falle y míralo fallar por la razón correcta, escribe la implementación mínima para que pase y luego refactoriza; nada de código de producción sin un test que falle primero."
| Tarea | Puntuación sin skill | Una frase | Con skill | Tokens sin skill | Tokens una frase | Tokens con skill | Skill leído |
|---|---|---|---|---|---|---|---|
| t1-slugify | 4.0 | 5.0 | 5.0 | 62k | 134k | 108k | 2/2 |
| t2-ratelimiter | 4.0 | 5.0 | 5.0 | 63k | 147k | 97k | 2/2 |
| t3-cart-bugfix | 4.0 | 4.0 | 5.0 | 69k | 97k | 116k | 2/2 |
Puntuación media: 4.0 sin vs 5.0 con el skill (delta +1.0). Tokens por ejecución: 65k vs 108k (1.65x); tiempo 55s vs 51s. Grupo de una frase: 4.67 (la mejora del skill frente a la frase: +0.33; la mejora de la frase frente a no usar skill: +0.67); la frase usa 127k tokens por ejecución, así que el skill consume 0.85 veces sus tokens.
Qué ocurrió
- El código fue igual de correcto: las suites de tests ocultos pasaron en las 12 ejecuciones de ambos grupos (12/12, 10/10 y 11/11 tests). En estas tareas pequeñas el skill no cambia que el código funcione.
- Lo que sí cambia es el orden del trabajo. En las 6 ejecuciones con skill, el archivo de test se escribió en un paso anterior a la implementación; en las 6 ejecuciones de control, el agente escribió tests e implementación en el mismo parche (o corrigió el bug primero y añadió el test después en la tarea del carrito). En la ejecución con skill que revisamos (slugify), el agente escribió el test, lo ejecutó para verlo fallar y luego escribió el código.
- Se activa solo por la descripción: el archivo del skill se leyó en 6/6 ejecuciones con skill aunque ningún prompt mencionaba TDD.
- Cuesta más: alrededor de 1.65 veces los tokens por ejecución (107k vs 65k) con un tiempo de reloj similar (51 s vs 55 s), porque el agente lee el skill y su archivo complementario y ejecuta el bucle varias veces.
- Versión de una frase (rojo-verde-refactor estricto, nada de código de producción sin un test que falle): media 4.67, entre el control (4.0) y el skill (5.0), con 127k tokens por ejecución frente a 65k del control (2.0x) y 108k del skill (1.2 veces los de este).
- Los tests se escribieron antes de la implementación en 0 de 6 ejecuciones de control, 4 de 6 de una frase y 6 de 6 del skill; las dos ejecuciones de una frase que no lo hicieron son de la tarea de corrección del carrito. El skill es el único grupo que lo hizo siempre, y lo hizo con menos comandos (10 por ejecución) que la frase (19).
Puntuación por dimensiones
| Dimensión | Puntuación | Motivo |
|---|---|---|
| 1_output_quality | 5.0 | Puntuación media de 5.00/5 con el skill (comprobaciones programáticas; véase la tabla por tarea). |
| 2_lift_vs_no_skill | 3.0 | +1.00 puntos frente a 4.00 sin el skill (n=2 por tarea; menos de ~1 punto es ruido). |
| 3_trigger | 5.0 | Skill leído en 6/6 ejecuciones con skill. |
| 4_instructions_portability | 4 | |
| 5_efficiency | 2 | 1.65x tokens (108k vs 65k por ejecución) y 0.93x tiempo (51s vs 55s). |
| 6_safety_hygiene | 5 |
Límites de esta prueba
- Los tests ocultos pasan todos en ambos grupos (techo), así que la mejora medida es la comprobación de proceso (test escrito antes de la implementación), que calculamos a partir del registro de eventos, no una diferencia de resultado.
- Las tareas son ejercicios pequeños de Python en un solo archivo; no se probaron repositorios más grandes, otros lenguajes ni la calidad de los tests (por ejemplo, mutation testing).
- n = 2 por grupo y tarea: las diferencias de menos de ~1 punto son ruido.
- La puntuación basada en reglas mide lo que las comprobaciones pueden ver; no puede juzgar el gusto ni si un resultado es el mejor posible.
Seguridad
Véase security.md. Escaneo: 0 CRITICAL / 0 HIGH / 0 MEDIUM. Veredicto: seguro de ejecutar (sandbox sin red). Un escaneo limpio no demuestra que un skill sea seguro.
Conclusión
Hace lo que dice: es el único grupo que escribió el test que falla primero en todas las ejecuciones (6/6, frente a 0/6 del control y 4/6 de la versión de una frase), con 1.7x los tokens del control y 0.85x los de la versión de una frase. La calidad final del código en estas tareas pequeñas fue la misma en todos los grupos, así que la mejora está en el proceso, no en el código.
Transcripción
Registro de ejecuciones: test-driven-development (Codex CLI, network off, per-run temp HOME/TMPDIR, one row per graded run.) Columnas: tarea, grupo-ejecución, puntuación (0-5), tokens, segundos, comprobaciones superadas, archivos de la skill que abrió el agente. t1-slugify control-1: puntuación 4.0, tokens 62017, s 55.5, comprobaciones 2/3, no abrió nada t1-slugify control-2: puntuación 4.0, tokens 62139, s 53.8, comprobaciones 2/3, no abrió nada t1-slugify oneliner-1: puntuación 5.0, tokens 135535, s 52.9, comprobaciones 3/3, no abrió nada t1-slugify oneliner-2: puntuación 5.0, tokens 134448, s 46.7, comprobaciones 3/3, no abrió nada t1-slugify treatment-1: puntuación 5.0, tokens 118034, s 56.3, comprobaciones 3/3, abrió test-driven-development t1-slugify treatment-2: puntuación 5.0, tokens 97974, s 48.3, comprobaciones 3/3, abrió test-driven-development t2-ratelimiter control-1: puntuación 4.0, tokens 63363, s 46.1, comprobaciones 2/3, no abrió nada t2-ratelimiter control-2: puntuación 4.0, tokens 63431, s 98.9, comprobaciones 2/3, no abrió nada t2-ratelimiter oneliner-1: puntuación 5.0, tokens 140042, s 60.8, comprobaciones 3/3, no abrió nada
18 ejecuciones, 3 artefactos
Resultado de ejemplo
SOTA · With the skill: test_slug.py (t1-slugify, run 1, Codex)
import unittest from slug import slugify class SlugifyTests(unittest.TestCase): def test_normalizes_text(self): cases = [ ('Hello, World!', 'hello-world'), (' --ABC__123\t\nxyz!! ', 'abc-123-xyz'), ('café déjà vu 12٣', 'caf-d-j-vu'), ('İ X', 'i-x'), ('already-a-slug', 'already-a-slug'), ] for text, expected in cases: with self.subTest(text=text): self.assertEqual(slugify(text), expected) def test_empty_result_uses_fallback(self): for text in ('', '--- !\t', '中文', '😀'): with self.subTest(text=text): self.assertEqual(slugify(text), 'n-a') def test_length_limits_respect_word_boundaries(self): cases = [ ('Hello, World!', 8, 'hello'), ('Hello, World!', 11, 'hello-world'), ('Hello, World!', 20, 'hello-world'), ('Hello, World!', 5, 'hello'), ('Hello, World!', 6, 'hello'), ('one two three', 7, 'one-two'), ('one two three', 9, 'one-two'), ('Supercalifragilistic', 5, 'super'), ('Supercalifragilistic next', 5, 'super'), ('abc', 1, 'a'), ('abc', 0, ''), ('!!!', 1, 'n'), ('!!!', 2, 'n'), ('!!!', 3, 'n-a'), ] for text, limit, expected in cases: with self.subTest(text=text, limit=limit): self.assertEqual(slugify(text, limit), expected) def test_explicit_none_leaves_length_unlimited(self): self.assertEqual(slugify('Hello, World!', None), 'hello-world') if __name__ == '__main__': unittest.main()