# Objective Guard

Runtime de verificación continua para agentes de programación. Detecta errores deterministas, desviaciones del objetivo y expansión de scope sin evidencia **antes** de que el agente acumule más trabajo sobre una decisión incorrecta.

El costo más evitable de un error de un agente no es cometerlo, sino descubrirlo varios pasos después, cuando ya hay nuevas decisiones que dependen de él. Objective Guard cierra esa brecha dándole al agente feedback programático en el primer momento en que existe evidencia reproducible de una violación.

> **Estado:** alpha funcional y portable para repositorios Git de JavaScript. Los detectores universales son deliberadamente acotados: sintaxis rota, tests debilitados, stubs en código de producción y dependencias nuevas. Que el guard pase significa únicamente que los checks en scope no encontraron ninguna violación — no es prueba de que el objetivo se haya alcanzado.

**Idioma:** el inglés es el idioma canónico de la documentación. Este archivo es la versión alternativa en español ([README.md](README.md)).

## Índice

- [Por qué](#por-qué)
- [Inicio rápido](#inicio-rápido)
- [Conceptos centrales](#conceptos-centrales)
- [Ciclo de vida de la ronda](#ciclo-de-vida-de-la-ronda)
- [Verificación y cierre de ronda](#verificación-y-cierre-de-ronda)
- [Integración con harnesses de agentes](#integración-con-harnesses-de-agentes)
- [Gobernanza: política de KPIs y observabilidad del scope](#gobernanza-política-de-kpis-y-observabilidad-del-scope)
- [Evidencia y telemetría](#evidencia-y-telemetría)
- [Excepciones deliberadas](#excepciones-deliberadas)
- [Documentación](#documentación)
- [Desarrollo](#desarrollo)
- [Límites epistémicos](#límites-epistémicos)

## Por qué

Un agente funciona bien mientras el contexto relevante se mantiene chico y observable. A medida que un repositorio crece, el agente puede ubicar mal el problema, construir sobre una hipótesis equivocada, ampliar progresivamente el cambio, debilitar tests para que una solución pase, o declarar éxito sin evidencia suficiente.

Objective Guard no intenta juzgar la intención. Hace explícitas y verificables tres cosas:

| Pregunta | Mecanismo |
| --- | --- |
| ¿Esta edición está deterministamente rota? | Detectores universales, sin configuración requerida |
| ¿Este trabajo sigue sirviendo al objetivo declarado? | Contrato tipado con objetivo, ronda, key results y scope |
| ¿El claim de cierre está respaldado por evidencia reproducible? | Checks, criterios y obligaciones declarados al cierre de la ronda |

## Inicio rápido

El paquete está publicado como `@fyso/objective-guard`. Desde un clone:

```bash
npm install            # no runtime dependencies; Node >= 20
npm test               # verify the alpha in your environment
npm install -g @fyso/objective-guard  # expone el binario `oguard` globalmente
```

Dentro de este repositorio, usá `node src/cli.mjs <command>`. En cualquier otro repositorio Git, usá el binario `oguard` linkeado (o `node /path/to/objective-guard/src/cli.mjs`).

Una primera ronda mínima:

```bash
oguard init
oguard intent --objective-id O-1 --objective "Protect checkout" --task-type bugfix --scope "src/**,test/**"
oguard intent-scan
# Review or revise the local draft, then freeze only the validated hypothesis:
oguard start --from-intent --round-id R-1 --round "Add regression" --kr-id KR-1 --kr "Checkout has a regression test"
git add oguard.contract.json && git commit -m "open round R-1"
oguard task-flow          # required before the first material edit
oguard check --file src/example.mjs
oguard align
oguard round-end
```

Paso a paso, con el significado de cada salida: **[docs/getting-started.es.md](docs/getting-started.es.md)**.

## Conceptos centrales

**Contrato.** `oguard.contract.json` es un artefacto de tarea versionado: objetivo, ronda, key results, tipo de tarea, contexto de trabajo, globs de scope, non-goals, checks declarados, criterios y obligaciones. Commiteálo antes de anclar un plan.

**Plan.** `oguard plan-template` imprime un plan mínimo derivado del contrato tipado. Guardalo, revisalo y commiteálo como `oguard.plan.json` antes de `anchor-plan`:

```json
{
  "schema_version": 1,
  "objective": { "id": "O-1", "statement": "Protect checkout" },
  "key_results": [{ "id": "KR-1", "statement": "Checkout has a regression test" }]
}
```

**Estado local.** `.oguard/` es estado operacional local, append-only, y debe quedar fuera de Git (git-ignored). `oguard.contract.json`, `oguard.plan.json` y `oguard.kpis.json` son los artefactos versionados.

**Intent.** `oguard intent` es una fase local y revisable *anterior* al contrato. Guarda un objetivo tentativo, tipo de tarea y scope candidato en `.oguard/intent.json`; `intent-scan` resuelve sólo archivos observables por Git que coinciden con esos globs y lista tests candidatos. No interpreta semántica ni concede preflight. El agente puede corregir el intent y repetir el scan; `start --from-intent` copia la versión elegida al contrato congelado y registra el hash del borrador y el conteo del scan. Una vez que existe un contrato tipado, `intent` se rechaza — un cambio de dirección debe ser una ronda sucesora explícita.

**Checks, criterios, obligaciones.** Se declaran al abrir la ronda, nunca editando el contrato a mano después. Una ronda `feature` puede vincular un mismo criterio reproducible a behavior y compatibility:

```bash
oguard start ... --task-type feature \
  --check test=npm,test --check-timeout-ms 900000 \
  --criterion-id C-1 --criterion "Feature behavior and compatibility pass" --criterion-checks test \
  --obligation behavior=C-1 --obligation compatibility=C-1
```

El timeout declarado admite hasta una hora. El planner descubre `test`, `lint` y `typecheck` desde `package.json`, pero sólo ejecuta comandos declarados explícitamente en `oguard.contract.json#checks`. Los checks descubiertos pero no configurados quedan como una recomendación visible: por sí solos no degradan `verification` ni bloquean una ronda cuyos checks y criterios declarados sí pasaron.

Para rondas `feature`, declará `--criterion-id`, `--criterion` y `--criterion-checks` al abrir la ronda. Sin checks reproducibles, el guard mantiene behavior y compatibility como `unknown`, y los resultados de tests ejecutados manualmente **no** se acreditan retroactivamente a un contrato congelado. El remedio es una ronda sucesora con los checks declarados — no mutar la evidencia de la ronda ya abierta.

**Contexto de trabajo.** Para merge, rebase, migración o cambios generados, declaralo antes de editar: `oguard next-round ... --work-context merge`. Si el cambio exógeno deja menos del 50% de la superficie dentro del scope, el veredicto de alineación es `not-evaluable`: preserva los checks fallidos pero evita contar ruido de integración como deriva del agente.

## Ciclo de vida de la ronda

```mermaid
flowchart LR
    I[intent + intent-scan<br/>local draft] --> S[start --from-intent<br/>frozen contract]
    S --> T[task-flow<br/>preflight before first edit]
    T --> E[edits<br/>check --file]
    E --> A[align<br/>drift verdict]
    A --> R[round-end<br/>evidence + baseline]
    R --> N[next-round<br/>archived transition]
    N --> T
```

`oguard next-round` exige un árbol limpio y un baseline activo que coincida con el contrato. Antes de instalar la ronda nueva, archiva ambos artefactos bajo `.oguard/history/` y registra una transición append-only, por lo que no puede usarse para acomodar un diff que ya existe.

## Verificación y cierre de ronda

`round-end` siempre aplica los detectores universales a los archivos modificados, valida el diff y conserva evidencia.

| Modo | Comportamiento |
| --- | --- |
| `oguard round-end --mode fast` | Conserva la incertidumbre como `unknown` |
| `oguard round-end --mode final` | Bloquea si un criterio requerido queda en `unknown` |

Los checks pueden acotarse con `modes: ["fast"]` o `modes: ["final"]`; sin ese campo aplican a ambos. Un candidato omitido nunca amplía un `pass`: queda registrado como `skipped` con `verification: "incomplete"`.

Antes de la primera edición material, el agente debe ejecutar `oguard task-flow --json`. Un resultado `ready` resume objetivo, ronda, tipo de tarea, contexto de trabajo, scope, non-goals y estado de gobernanza. `action-required` termina con código no cero y exige resolver contrato, baseline o gobernanza antes de mutar cualquier cosa.

## Integración con harnesses de agentes

| Harness | Guía |
| --- | --- |
| Claude Code | [docs/guides/claude-code.es.md](docs/guides/claude-code.es.md) |
| Codex | [docs/guides/codex.es.md](docs/guides/codex.es.md) |
| Agregar otro harness | [docs/guides/README.es.md](docs/guides/README.es.md) |

En Claude y Codex, el prompt global inyecta `task-flow` al inicio de cada pedido, y los hooks globales `PreToolUse` para `Edit|Write` además ejecutan el gate local. Una autorización `ready` se guarda contra el hash del contrato y expira a la hora; sin ella, la herramienta estructurada recibe `permissionDecision: deny`.

Dos límites deliberados: el gate deja sin bloquear a los repositorios sin contrato, y no intenta clasificar escrituras arbitrarias realizadas dentro de comandos de shell.

## Gobernanza: política de KPIs y observabilidad del scope

Para volver los KPIs obligatorios para el agente, versioná `oguard.kpis.json` en la raíz del repositorio. `oguard task-flow` carga y valida esa política automáticamente. Una violación con severidad `block` no concede preflight, por lo que el gate de edición deniega la mutación. El hash de la política queda ligado a la autorización: modificarla obliga a correr `task-flow` de nuevo. `warn` conserva visibilidad sin frenar el trabajo, y `unknown` sólo significa que todavía no hay suficiente muestra para concluir.

El scope también se audita por observabilidad: un glob que sólo resuelve a archivos ignorados emite `scope-unobservable`. Los archivos de contabilidad (`oguard.contract.json`, `oguard.plan.json`, `oguard.kpis.json` y `.oguard/**`) nunca acreditan un key result por sí mismos. Para trabajo de discovery, `task.assumption_ledger_required` exige una lista de supuestos con path, evidencia textual y, opcionalmente, un check ya declarado.

## Evidencia y telemetría

```bash
oguard evidence export --output evidence/oguard.json
oguard evidence dataset calibration --output evidence/runs/calibration.json
oguard evidence dataset evaluation --output evidence/runs/evaluation.json
```

`oguard evidence dataset` produce datasets pasivos y separados para `calibration` y `evaluation`. Registra features y fórmulas versionadas; no activa alertas, umbrales ni cambios de política.

Cada decisión pre-edición también llega al inventario global en forma sanitizada: harness, hash del repositorio, `allow`/`deny`, código de razón y duración. No conserva paths, prompt ni contenido de archivos.

| Comando | Qué reporta |
| --- | --- |
| `oguard inventory report --json` | Totales, incluyendo `pre_edit` |
| `oguard inventory kpis --json [--policy path.json]` | Cobertura de preflight, tasa de denegación, p95 de latencia, resolución de findings; valida `{ min?, max?, min_samples?, severity?: "warn"\|"block" }` |
| `oguard inventory dashboard --days 7 --json` | Adopción, disciplina de flujo, intervenciones y resolución, cortado por proyecto y harness |

El dashboard declara explícitamente `causal_effect: not-evaluable`: la telemetría de uso por sí sola no prueba que el guard haya evitado una desviación ni que haya ahorrado tiempo o tokens.

Para consolidar telemetría desde cualquier fuente SSH sin copiar contratos, planes ni contenidos de repositorio, creá localmente (fuera de Git) `~/.oguard/inventory/sources.json`:

```json
{
  "schema_version": 1,
  "sources": [
    { "id": "mac-mini", "host": "user@host.example.ts.net", "path": ".oguard/inventory/events.jsonl" }
  ]
}
```

```bash
npm run inventory:pull
```

El colector lee exclusivamente paths bajo `.oguard/` por SSH, permite sólo el esquema sanitizado de telemetría, y agrega únicamente eventos cuyo fingerprint no estuviera ya importado. Conserva su estado por `id` en `~/.oguard/inventory/remote-imports/`, por lo que repetirlo es idempotente. `--dry-run` inspecciona el delta sin escribir, `--source <id>` selecciona una fuente, y `--config <path>` usa una configuración local distinta.

## Excepciones deliberadas

| Comando | Cuándo | Garantía |
| --- | --- | --- |
| `oguard accept-baseline --reason <text> --actor <text>` | Una ronda cerrada cuyo resultado no promocionable fue aceptado — por ejemplo, deuda de rendimiento durante un piloto | Exige un árbol limpio; conserva el baseline anterior y el status fallido/unknown en un evento append-only. **No** transforma ese resultado en `pass` |
| `oguard adopt-baseline` | Migración única para un contrato tipado histórico sin baseline | Exige un árbol limpio, no reescribe el contrato, registra `baseline-adopted`. Después, la transición normal vuelve a ser `next-round` |

## Documentación

| Punto de entrada | Contenido |
| --- | --- |
| [docs/README.es.md](docs/README.es.md) | Índice canónico de documentación y regla de precedencia |
| [docs/getting-started.es.md](docs/getting-started.es.md) | De un repositorio sin modificar a una primera ronda cerrada |
| [docs/guides/README.es.md](docs/guides/README.es.md) | Guías de integración por harness (Claude Code, Codex, …) |
| [docs/product/01-vision-and-thesis.es.md](docs/product/01-vision-and-thesis.es.md) | Problema, tesis actual, principios, límites epistémicos |
| [docs/product/02-product-contract.es.md](docs/product/02-product-contract.es.md) | Objetivo, usuarios, scope, non-goals, requisitos |
| [docs/product/03-signal-and-decision-model.es.md](docs/product/03-signal-and-decision-model.es.md) | Clases de señal, superficie de cambio, evidencia, política de decisión |
| [docs/product/04-technical-architecture.es.md](docs/product/04-technical-architecture.es.md) | Componentes, flujo por niveles, persistencia, modos de fallo |
| [docs/product/05-scientific-validation.es.md](docs/product/05-scientific-validation.es.md) | Hipótesis, escalera de evidencia, métricas, criterios de falsación |
| [docs/product/06-roadmap-and-criteria.es.md](docs/product/06-roadmap-and-criteria.es.md) | Orden de construcción, MVP, criterios de aceptación, decisiones diferidas |
| [docs/product/07-phase-1-calibration-protocol.es.md](docs/product/07-phase-1-calibration-protocol.es.md) | Protocolo de calibración de la Fase 1 |
| [docs/functionality/INDEX.es.md](docs/functionality/INDEX.es.md) | Actores, capacidades, reglas y la matriz de tests funcionales |
| [docs/episodes/README.es.md](docs/episodes/README.es.md) | Registro append-only de rondas reales que cambiaron el producto |
| [docs/initial-research/README.es.md](docs/initial-research/README.es.md) | Hipótesis históricas, PRDs v0 y revisiones adversarias |

## Desarrollo

```bash
npm test                          # node --test test/*.test.mjs
npm run validate:docs             # documentation guard
npm run round:end                 # dogfood the guard on the current round
npm run benchmark                 # calibration benchmark
npm run calibration:gate          # F1 calibration gate
npm run synthetic                 # synthetic corpus
npm run synthetic:trajectories    # Phase 4 task-trajectory corpus
```

`npm run validate:docs` verifica la topología documental, los contratos de capacidades, la matriz funcional, el pairing de idiomas y los enlaces relativos. No prueba que la tesis sea verdadera; prueba que el entregable documental satisface un contrato explícito y reproducible.

`npm run synthetic:trajectories` reproduce el corpus de tareas de la Fase 4 y escribe `synthetic/results/task-trajectories-v1.json`. Es cobertura construida con etiquetas conocidas — no un benchmark de eficacia ni un clasificador.

Estructura del repositorio:

```
src/          CLI, detectors, contract, alignment, gate, inventory
test/         node:test suites (the executable specification)
scripts/      docs guard, harness prompt scripts, telemetry collector
docs/         canonical English documentation + Spanish .es.md counterparts
synthetic/    synthetic corpora and runners
benchmarks/   calibration and gate benchmarks
evidence/     exported evidence and datasets
```

## Límites epistémicos

- Un `pass` significa que los checks en scope no encontraron ninguna violación. No es evidencia de que el objetivo se haya alcanzado, ni de que el guard sea útil.
- `unknown` significa evidencia insuficiente, no fallo. El guard preserva esa distinción a propósito.
- La curva de "chico bien, mediano mal, grande estructurado mejor" sigue siendo una hipótesis confundida. Objective Guard no presume que sea universal; recolecta evidencia para medir cuándo aparece.
- La telemetría de uso prueba adopción, no beneficio.

Las rondas reales en las que el guard se perdió una señal, disparó tarde, o en las que el agente sustituyó su propio objetivo, quedan registradas en [docs/episodes/README.es.md](docs/episodes/README.es.md) en lugar de corregirse en silencio.
