Phase 14 - Lesson 36
Contratos de Alcance y Límites de Tareas
This lesson includes a graded coding exercise that runs in your browser, unlocked with lifetime access.
El modelo no sabe dónde termina el trabajo. Un contrato de alcance es un archivo por tarea que define dónde comienza el trabajo, dónde termina y cómo revertirlo si se desborda. El contrato convierte el "mantenerse en el alcance" de un deseo a una verificación.
Tipo: Build Lenguajes: Python (stdlib) Requisitos previos: Fase 14 · 32 (Minimal Workbench), Fase 14 · 33 (Rules as Constraints) Tiempo: ~50 minutos
Objetivos de Aprendizaje
- Escribir un contrato de alcance que un agente lea al inicio de la tarea y un verificador lea al final.
- Especificar archivos permitidos, archivos prohibidos, criterios de aceptación, plan de reversión y límites de aprobación.
- Implementar un verificador de alcance que compare un diff contra el contrato e identifique violaciones.
- Hacer que la desviación de alcance sea visible, automática y revisable.
O Problema
Los agentes se desvían de su alcance. La tarea es "corregir el bug de inicio de sesión". El diff afecta la ruta de login, el asistente de correo electrónico, el controlador de la base de datos, el README y el script de lanzamiento. Cada cambio tenía un motivo plausible en su momento. Juntos, representan un cambio diferente al que fue revisado.
La desviación de alcance (scope creep) es el modo de fallo menos monitoreado en el trabajo con agentes porque el agente narra cada paso de buena fe. La solución no es un prompt más estricto. La solución es un contrato en disco que defina lo que se prometió y una verificación que compare el resultado con la promesa.
El Concepto
flowchart LR
Task[Tarea] --> Contract[scope_contract.json]
Contract --> Agent[Bucle del Agente]
Agent --> Diff[diff final]
Diff --> Checker[scope_checker.py]
Contract --> Checker
Checker --> Verdict{¿dentro del alcance?}
Verdict -- sí --> Verify[Puerta de Verificación]
Verdict -- no --> Block[bloqueo + pregunta abierta]
Qué va en un contrato de alcance
| Campo | Propósito |
|---|---|
task_id |
Vincula a la tarea en el tablero |
goal |
Una frase que el revisor puede verificar |
allowed_files |
Globs que el agente puede escribir |
forbidden_files |
Globs que el agente no debe tocar ni por accidente |
acceptance_criteria |
Comandos de prueba o líneas de aserción que demuestran la conclusión |
rollback_plan |
Un párrafo que el operador puede ejecutar si se requiere una detención |
approvals_required |
Acciones fuera del alcance que necesitan aprobación humana explícita |
Un contrato sin forbidden_files está incompleto. El espacio negativo es la mitad del contrato.
Globs, no rutas completas
Los repositorios reales mueven archivos. Vincule los contratos a globs (app/**/*.py, tests/test_signup*.py) para que una refactorización entre sesiones no invalide el contrato.
La reversión es parte del alcance
Listar cómo revertir obliga al autor del contrato a pensar en lo que podría salir mal. Un contrato del cual no se pueda revertir es un contrato que no debería ser aprobado.
La verificación de alcance es una verificación de diff
El agente escribe un diff. El verificador lee el diff, los globs permitidos, los globs prohibidos y una lista de cualquier comando de aceptación que se haya ejecutado. Cada violación es un hallazgo etiquetado que la puerta de verificación puede rechazar.
Constrúyalo
code/main.py implementa:
- Esquema de
scope_contract.json(subconjunto de JSON Schema, arrays de globs). - Un analizador (parser) de diff que convierte una lista de archivos afectados y una lista de comandos ejecutados en un
RunSummary. - Un
scope_checkque devuelve(violations, in_scope, off_scope)contra el contrato. - Dos ejecuciones de demostración: una que permanece dentro del alcance y otra que se desvía. El verificador señala la desviación con el archivo exacto y el motivo.
Ejecútelo:
python3 code/main.py
Salida: el contrato, las dos ejecuciones, los veredictos por ejecución y un scope_report.json guardado.
Patrones de producción en el mundo real
Un profesional que implementa "specsmaxxing" (contratos de alcance en YAML antes de invocar al agente) informa que la tasa de desvíos en "madrigueras de conejo" (rabbit-holes) cayó del 52% al 21% en tres semanas sin cambiar al agente. El contrato hizo el trabajo, no el modelo. Tres patrones hacen que esta ganancia perdure.
Presupuestos de violación, no fallas binarias. agent-guardrails (la puerta de fusión de código abierto utilizada por Claude Code, Cursor, Windsurf, Codex a través de MCP) incluye un violationBudget por tarea: los desvíos menores del alcance dentro del presupuesto se muestran como advertencias; solo cuando se excede el presupuesto la puerta de fusión rechaza el cambio. Combínelo con violationSeverity: "error" | "warning". El presupuesto es la diferencia entre una puerta que se implementa y una que el equipo desactiva porque terminó odiándola.
Asimetría de severidad por familia de rutas. Las escrituras fuera del alcance en docs/** suelen ser de advertencia (warn); las escrituras fuera de alcance en scripts/**, migrations/**, config/prod/** siempre se bloquean (block). Esta asimetría debe vivir en el contrato, no en el entorno de ejecución, porque es específica del proyecto y cambia según la tarea.
Presupuestos de tiempo y red junto a presupuestos de archivos. Un campo time_budget_minutes limita el tiempo real transcurrido; el entorno de ejecución se niega a continuar más allá de este límite sin una nueva aprobación. Una lista de permitidos network_egress en nombres de host evita que el agente acceda silenciosamente a una API externa que no formaba parte de la tarea. Estas también son dimensiones de alcance; los globs de archivos son necesarios, pero no suficientes.
Semántica de fusión de múltiples contratos (privilegio mínimo). Cuando se aplican dos contratos de alcance (por ejemplo, un contrato global del proyecto más uno específico de la tarea), la fusión es: hacer la intersección de allowed_files (ambos contratos deben permitir la ruta), hacer la unión de forbidden_files (cualquiera puede prohibirla), time_budget_minutes es el más restrictivo (mínimo) y approvals_required se acumula. network_egress es None para no aplicar restricciones, [] para denegar todo, [...] como lista de permitidos; bajo fusión, None delega al otro lado, dos listas se intersectan y denegar todo permanece como denegar todo. Especifique esto en el esquema del contrato para que la fusión sea mecánica y revisable.
Utilícelo
Patrones de producción:
- Comandos de barra diagonal en Claude Code. Un comando
/scopeescribe el contrato y lo fija como contexto de la sesión. Los subagentes leen el contrato antes de actuar. - PRs de GitHub. Envíe el contrato como un archivo JSON en el cuerpo del PR o como un artefacto registrado. El CI ejecuta el verificador de alcance contra el diff de fusión.
- Interrupciones de LangGraph. Una violación de alcance activa una interrupción; el controlador le pregunta al humano si el contrato necesita ampliarse o si el agente debe retroceder.
El contrato viaja con la tarea. Cuando la tarea se cierra, el contrato se archiva bajo outputs/scope/closed/.
Envíelo
outputs/skill-scope-contract.md genera un contrato de alcance para una descripción de tarea y un verificador compatible con globs que se ejecuta en CI en cada diff de agente.
Ejercicios
- Agregue un campo
network_egressque enumere los hosts externos permitidos. Rechace ejecuciones que interactúen con otros hosts. - Extienda el verificador para fallar de forma suave (fail soft) en
docs/**y de forma estricta (fail hard) enscripts/**. Justifique la asimetría. - Haga que el contrato derive
allowed_filesde un campogoalusando un conjunto de reglas estáticas (sin LLM). ¿Qué sale mal en el primer caso extremo? - Agregue un
time_budget_minutesy niéguese a continuar una vez que el tiempo real lo supere. - Ejecute dos contratos contra el mismo diff. ¿Cuál es la semántica de fusión correcta cuando se aplican ambos?
Términos Clave
| Término | Qué dice la gente | Qué significa realmente |
|---|---|---|
| Contrato de alcance | "El resumen de la tarea" | JSON por tarea que enumera archivos permitidos/proibidos, aceptación, reversión |
| Desviación de alcance (scope creep) | "También afectó a..." | Archivos fuera del contrato modificados en la misma tarea |
| Plan de reversión | "Podemos revertir" | El manual de operaciones de un párrafo para detener el proceso |
| Límite de aprobación | "Requiere autorización" | Una acción listada en el contrato que requiere aprobación humana explícita |
| Verificación de diff | "Auditoría de rutas" | Comparación de archivos modificados contra los globs del contrato |
Lecturas Adicionales
- Interrupciones human-in-the-loop en LangGraph
- Políticas de aprobación de herramientas del OpenAI Agents SDK
- logi-cmd/agent-guardrails — puertas de fusión y validación de alcance — presupuestos de violación, niveles de severidad
- Dev|Journal, Preventing AI Agent Configuration Drift with Agent Contract Testing — modo
--strictsin dependencias externas - Agentic Coding Is Not a Trap (logs de producción) — recibos de specsmaxxing: 52% → 21%
- Globs de permisos de OpenCode — alcance detallado por permiso
- Knostic, AI Coding Agent Security: Threat Models and Protection Strategies — el alcance como parte del privilegio mínimo
- Augment Code, AI Spec Template — sistema de límites de tres niveles (must/ask/never)
- Fase 14 · 27 — defensas contra injección de prompts que se emparejan con bloqueos de alcance
- Fase 14 · 33 — el conjunto de reglas que este contrato especializa por tarefa
- Fase 14 · 38 — la puerta de verificación a la que se reporta el verificador