Caso guiado de principio a fin

Por: Artiko
oddcaso-practicoprotocoloejemplo

Caso guiado de principio a fin

Objetivos

  • Aplicar los siete pasos a pedidos reales.
  • Ver cómo las mismas reglas producen recorridos distintos.
  • Practicar la clasificación, el documento y el cierre.

Caso ficticio. El proyecto, los commits y las salidas de este capítulo son inventados con fines didácticos. Las reglas aplicadas son las del protocolo. El comportamiento real depende del modelo y del runtime.


El proyecto

Facturín es una aplicación de facturación en TypeScript con pruebas en Bun, y una CLI facturin que usan también algunos scripts de clientes. Usa Claude Code con Gentle AI, RDD activo y Engram.


Pedido 1: una pregunta

¿Por qué la factura 1042 sale con el IVA duplicado?

PasoDecisión
AuthorizeInvestigación: solo lectura
ExploreLee src/billing/tax.ts y reproduce el cálculo
UncertaintyNo hay decisión de producto

Respuesta del agente:

El IVA se aplica dos veces cuando la factura tiene un descuento: applyDiscount()
llama a computeTax() en src/billing/tax.ts:48 y total() vuelve a llamarla
en src/billing/total.ts:22. La factura 1042 tiene un descuento del 10%.

No cambié nada. Si quieres, lo corrijo.

No hubo documento, ni línea Risk ni escritura. Encontrar el error no autorizó corregirlo.


Pedido 2: un arreglo con riesgo nombrado

Corrígelo.

“Corrígelo”, contra la propuesta inmediatamente anterior, es una autorización clara.

Classify

CriterioResultado
ComprendidaSí: se sabe qué y dónde. Una tanda de lectura bastó
Riesgo contenidoPor comprobar: podría afectar a facturas emitidas y a scripts de clientes
Reanudable desde el diffSí

Antes de decidir mira el código: total() solo calcula, no modifica facturas guardadas. Con esa mirada acotada revisa los puntos candidatos:

Punto¿Aplica?
1, datosNo: no altera lo persistido
3, contratoSí: la salida de facturin total cambia para quien tenga descuentos, y la consumen scripts de clientes

Sin embargo, es justamente el cambio pedido. La exclusión del punto 3 dice que los cambios solicitados no son de alto riesgo por sí mismos. Solo lo serían las roturas no pedidas en código compartido.

El parent comprueba eso con el helper compartido: computeTax() lo usa también facturin preview. Corre la comprobación diferencial sobre ese comando.

Implementar inline

# RED observado: una prueba por la regla
$ bun test src/billing/total.test.ts
✗ total no aplica el IVA dos veces con descuento  # esperado 119, recibido 141.61

# GREEN tras el cambio de una línea
$ bun test src/billing/total.test.ts
✓ 12 pasan

# PRESERVE: una prueba para facturin preview, que comparte el helper
# Diferencial en una copia de la base dentro de mktemp -d
$ diff <(base/facturin preview 1041) <(facturin preview 1041)
# sin diferencias

# Suite completa, una vez
$ bun test
✓ 318 pasan

Cierre

Corregí el IVA duplicado con descuento: total() ya no recalcula el impuesto.

Comprobaciones:
- RED observado y luego GREEN en total.test.ts
- bun test: 318 pasan
- Diferencial de facturin preview contra la base: sin diferencias

Risk: none. La salida cambia solo para facturas con descuento, que es lo pedido,
y los otros comandos que comparten computeTax() no cambian.

No hice commit. Falta decidir si lo incluyes en la siguiente entrega.
flowchart LR
    A["Corrígelo"] --> B["Comprendida y reanudable"]
    B --> C["RED, GREEN y PRESERVE inline"]
    C --> D["Diferencial"]
    D --> E["Suite una vez"]
    E --> F["Risk: none, sin commit"]

Una variante: si el diferencial hubiera mostrado un cambio en facturin preview, la línea sería Risk: item 3 y se activaría el verificador. Además habría que corregir la regresión y fijarla con una prueba.


Pedido 3: una feature grande

Agrega facturación recurrente mensual. Quiero que corra en varias etapas porque espero la confirmación del banco para el cobro automático. El mensaje de error debe ser exactamente “No se pudo programar el cobro”.

Authorize y Explore

Autorizado. El parent lee el módulo de facturas y lo que existe de programación. Los archivos que va a editar los lee inline. Solo pide un explorador si necesita un mapa que exceda la tanda de evidencia, y aquí necesita uno, porque no conoce el módulo de pagos.

Resolve uncertainty

Queda una decisión de producto: ¿qué pasa si el cobro falla tres veces? Hay una sola pregunta:

¿Qué hacemos cuando un cobro recurrente falla tres veces seguidas?
A. Suspender la suscripción y avisar
B. Seguir reintentando cada mes

El usuario responde “A”. El parent espera esa respuesta antes de seguir con lo que depende de ella.

Classify

La prueba de reanudación falla por dos motivos que el propio pedido menciona: varias etapas y una espera externa. Es grande. Eso activa el Tracking trigger, y no un writer.

Track before the first write

Mensaje al usuario, en una línea:

Creé odd/tasks/recurring-billing.md con 4 tareas.
# Facturación recurrente mensual
Branch: `feat/recurring-billing` · Delivery: ask-on-risk · Runner: `bun test`
Engram mirror: `odd/recurring-billing/tasks` · Route: inline salvo motivo

## Specs
S1. "Agrega facturación recurrente mensual." Aceptación: se genera una factura por mes por suscripción activa.
S2. Mensaje exacto: "No se pudo programar el cobro".
S3. Tres fallos seguidos, respuesta del usuario: "A" a "Suspender la suscripción y avisar".
S4. "espero la confirmación del banco para el cobro automático". Aceptación: el cobro automático no se activa antes de esa confirmación.

## Tasks
- [ ] T1 (S1) inline · modelo y generación mensual
- [ ] T2 (S2, S3) inline · programación de cobros y fallos
- [ ] T3 (S1) inline · Risk item 1, migración de la tabla de suscripciones
- [ ] T4 (S4) bloqueada · activar el cobro cuando el banco confirme

## Log
L1 2026-11-06 usuario (textual): > Agrega facturación recurrente mensual. Quiero que corra en varias etapas porque espero la confirmación del banco para el cobro automático. El mensaje de error debe ser exactamente "No se pudo programar el cobro".
L2 2026-11-06 pregunta: fallos seguidos. Usuario (textual): > A

Por el contrato de idioma, un agente generaría este documento en inglés y conservaría las citas en tu idioma. Aquí se muestra en español para facilitar la lectura.

Observa lo que no hay: el agente no agregó reintentos configurables, panel de administración ni notificaciones por correo, porque nadie los pidió.

Implementar

gitGraph
    commit id: "main"
    branch feat/recurring-billing
    checkout feat/recurring-billing
    commit id: "T1, generación mensual"
    commit id: "T2, cobros y fallos"
    commit id: "T3, migración, Risk item 1"
TareaRutaComprobacionesResultado
T1Inline, sin motivo de writerRED y GREEN, 180 líneasrisk: medium, under_budget
T2InlineRED y GREEN, 190 líneasrisk: medium, under_budget
T3Inline, commit propioRED y GREEN, ensayo en base aisladarisk: high, review_due: true

Al crear el documento, el pronóstico era de unas 350 líneas y no activó nada. Después de T2, el conteo acumulado son 370 líneas y, al sumar la migración que falta, el pronóstico actualizado supera 400. Antes del siguiente commit aplica ask-on-risk: el parent pregunta una vez por la estrategia de cadena. El usuario elige stacked-to-main. La elección queda en el documento.

T3: el punto de alto riesgo

La migración modifica datos que no se pueden reconstruir. El orden es:

  1. Cerrar antes la porción abierta. T1 y T2 están pendientes under_budget, y se evalúan como porción antes de T3.
  2. Commit propio para T3.
  3. Autoverificación de T3.
  4. Verificador independiente, con el documento completo, el commit base y las formas de las sondas. Corre las sondas en una copia con mktemp -d y devuelve un veredicto por S#.
  5. review assess devuelve high_risk. Con RDD activo, se ejecuta next_transition.command con lentes elegidas.
gentle-ai review assess --cwd . --agent claude-code \
  --base-ref a1b2c3d --committed-only --json \
  --escalate-item 1 --escalate-reason "migra la tabla de suscripciones"

El next_transition que devuelve este comando no lleva el escalamiento, así que el mismo par de flags se repite en START. Se piden las lentes risk,resilience, con este motivo: “migración de datos con posible fallo a mitad de camino”. El sobre de consentimiento llega al usuario sin resumirse. El usuario acepta.

Un hallazgo y su corrección

El verificador encuentra un bloqueo: si la migración falla a la mitad, queda en un estado no recuperable. El parent hace un lote de corrección y una recomprobación limitada a ese bloqueo. Pasa.

También encuentra un aviso: el formato de fecha de un reporte antiguo ya era inconsistente antes de esta rama. Lo reprodujo en la base, así que es un aviso, y no se corrige porque no está en el alcance.

Un cambio de requisito

Mejor que sean dos fallos seguidos, no tres.

S3. Dos fallos seguidos, corrección del usuario (L5): "Mejor que sean dos fallos seguidos, no tres". Respuesta anterior: "A".

- [ ] T2 (S2, S3) reabierta por L5 · ajustar el umbral

L5 2026-11-07 usuario (textual): > Mejor que sean dos fallos seguidos, no tres.

Solo cambian S3 y T2. T1 y T3 siguen hechas.

Interrupción y reanudación

Se acaba el día, y mientras T4 sigue bloqueada, el usuario dice “seguimos la próxima semana”. Una semana después, en una sesión nueva:

sequenceDiagram
    participant P as Parent nuevo
    participant E as Engram
    participant D as Archivo local
    P->>E: mem_context
    P->>E: mem_search recurring-billing
    P->>E: mem_get_observation
    P->>D: Leer odd/tasks/recurring-billing.md
    P->>P: Conciliar con git log y pruebas
    P->>P: T4 sigue bloqueada, informar

Cierre

Terminé T1, T2 y T3. T4 sigue bloqueada porque espera la confirmación del banco.

Comprobaciones:
- bun test: 342 pasan
- Verificador independiente en T3: S1 a S3 cumplidas, S4 sin cumplir porque espera al banco
- Revisión RDD de T3: aprobada y reconocida
- Sin ejecutar: cobro real, requiere el banco

Risk: item 1 (migración de la tabla de suscripciones)

Necesito tu decisión: ¿hago push de feat/recurring-billing para el primer PR?

Comparación de los tres recorridos

flowchart TD
    subgraph P1["Pedido 1: la pregunta"]
        A1["Authorize"] --> A2["Explore"] --> A3["Respuesta"]
    end
    subgraph P2["Pedido 2: el arreglo"]
        B1["Authorize"] --> B2["Explore"] --> B3["Classify"] --> B4["Inline con test-first"] --> B5["Close con Risk"]
    end
    subgraph P3["Pedido 3: la feature"]
        C1["Authorize"] --> C2["Explore"] --> C3["Una pregunta"] --> C4["Classify"] --> C5["Documento"] --> C6["Commits, verificador y RDD"] --> C7["Close"]
    end
AspectoPedido 1Pedido 2Pedido 3
Escrituras0InlineInline
Subagentes00Explorador y verificador
DocumentoNoNoSí
CommitsNoNoSí
Preguntas001 de producto, 1 de cadena
Revisión RDDNoNoSolo T3

Toda la feature del pedido 3 corrió inline, sin writers, porque nada cumplía el motivo de paralelismo. Es lo que el curso ha repetido: grande no significa delegado.


Actividad

Repite este capítulo con tu proyecto y los tres pedidos del capítulo 1. Para cada uno, escribe la clasificación, la ruta, el artefacto y la línea Risk. Si puedes, pídeselos después a tu agente con Gentle AI instalado y compara los resultados.


Autoevaluación

  1. En el pedido 3, ¿qué activó el documento de feature?

    • A. La cantidad de tareas
    • B. La palabra “recurrente”
    • C. La migración
    • D. Que falla la prueba de reanudación
  2. ¿Por qué no hubo writers en el pedido 3?

    • A. Porque nada cumplía un motivo de writer
    • B. Porque Claude Code no los admite
    • C. Porque RDD estaba activo
    • D. Porque el usuario los prohibió
  3. El verificador detectó una inconsistencia que ya existía en la base. ¿Cómo se trató?

    • A. Como un bloqueo
    • B. Como un motivo para ampliar el alcance
    • C. Como un aviso, sin corregirla
    • D. Se reabrió T1
  4. El usuario cambió el umbral de fallos. ¿Qué tareas se reabrieron?

    • A. Todas
    • B. Solo la vinculada a la especificación afectada
    • C. Las posteriores a T2
    • D. Ninguna: se creó una feature nueva
Respuestas
  1. D. Varias etapas y una espera externa hacen fallar esa prueba.
  2. A. Una tarea grande sin motivo se ejecuta inline.
  3. C. Un defecto preexistente es un aviso y un hallazgo no amplía el alcance.
  4. B. Se reescribe la S# afectada y se reabre su tarea.

Lista de control

  • Puedo trazar los tres recorridos sin ayuda.
  • Hago la comprobación de código compartido antes de declarar Risk: none.
  • Ubico la evaluación y el verificador en el orden correcto.
  • Aplico un cambio de requisito sin rehacer lo demás.

Fuentes

Reglas de internal/components/agentguidance/routing.go, internal/assets/skills/_shared/odd-orchestrator-sections.md y docs/usage.md. Ejemplo elaborado para este curso a partir de la frase de muestra de docs/quickstart.md.