# Primeros pasos con Objective Guard

Esta guía te lleva desde un repositorio Git sin modificar hasta una primera ronda cerrada con evidencia exportada.

## Qué hace Objective Guard

Objective Guard es un runtime de verificación continua para agentes de programación. Devuelve feedback determinista en el momento de la edición sobre cuatro detectores universales acotados, congela la intención en un contrato de tarea tipado (objetivo, ronda, key result, scope, non-goals), reporta señales de deriva entre el contrato declarado y la superficie de cambio observada, y persiste evidencia reproducible al cerrar una ronda.

Es una alpha funcional para repositorios Git JavaScript. Los detectores universales son deliberadamente acotados: tests recién deshabilitados o debilitados, stubs nuevos en producción, dependencias nuevas y errores de sintaxis JavaScript en archivos `.js`, `.mjs` y `.cjs`. Todo lo que va más allá proviene de checks que declarás vos.

## Requisitos

- Node.js 20 o posterior (`engines.node` es `>=20`). Sin dependencias de runtime.
- Un repositorio Git con al menos un commit. Los comandos de sesión y baseline resuelven `git rev-parse HEAD`, por lo que un repositorio vacío no puede abrir una ronda.
- Git disponible en el `PATH`. Toda medición de superficie, diff y baseline es una llamada a `git`.

El paquete público declara `oguard` para el CLI y `oguard-hooks` para la configuración de harnesses. Una instalación global expone ambos comandos.

En toda esta guía, `oguard` significa el binario instalado o bien `node /ruta/a/objective-guard/src/cli.mjs`. El CLI resuelve el repositorio destino desde el directorio de trabajo actual mediante `git rev-parse --show-toplevel`, así que invocar el `src/cli.mjs` de un clon desde dentro de otro repositorio opera sobre ese otro repositorio.

## Instalación

En este repositorio, invocá el CLI directamente y confirmá la superficie de comandos:

```bash
node src/cli.mjs --help
node src/cli.mjs task-flow --json
npm test
```

`--help` termina con código 2 e imprime el uso completo en stderr; eso es esperado. `npm test` ejecuta `node --test test/*.test.mjs`, que construye repositorios temporales y ejercita el flujo de punta a punta.

En cualquier otro repositorio Git, elegí una de estas formas:

```bash
# Opción A — sin instalar; ejecutar el CLI del clon desde dentro del repositorio destino
cd /ruta/a/tu-repositorio
node /ruta/a/objective-guard/src/cli.mjs task-flow --json

# Opción B — instalar desde el clon local para tener oguard en el PATH
npm install --global /ruta/a/objective-guard
cd /ruta/a/tu-repositorio
oguard task-flow --json

# Opción C — instalar el paquete público y configurar ambos harnesses soportados
npm install --global @fyso/objective-guard
oguard-hooks install --harness all
cd /ruta/a/tu-repositorio
oguard init
```

`oguard-hooks install --harness claude|codex|all` fusiona los hooks de Objective Guard en la configuración de harness a nivel usuario sin duplicar sus propias entradas. Usá `--dry-run` para inspeccionar primero las rutas de configuración destino. Nunca crea un contrato de tarea; corré `oguard init` desde cada repositorio que quieras gobernar.

## Tu primera ronda

Ejecutá esta secuencia en un repositorio Git con al menos un commit y árbol de trabajo limpio. El ejemplo abre una ronda `feature` para un objetivo de checkout, con scope en `src/**` y `test/**`.

1. **Crear el contrato placeholder.**

   ```bash
   oguard init
   ```

   Escribe `oguard.contract.json` con un objetivo placeholder (`O-UNSPECIFIED`) y `policy.goal_substitution=observe`. Se niega a sobrescribir un contrato existente. El placeholder es una rampa de entrada, no una configuración válida: no concede preflight y no permite pasar el gate pre-edición.

2. **Redactar una intención revisable.**

   ```bash
   oguard intent --objective-id O-CHECKOUT --objective "Protect checkout" \
     --task-type feature --scope "src/**,test/**"
   ```

   Guarda objetivo, tipo de tarea y scope candidato en `.oguard/intent.json`. Esto es estado local, no un contrato. `intent` sólo está disponible mientras el contrato siga siendo el placeholder; una vez que existe un contrato tipado se rechaza, porque un cambio de dirección debe ser una ronda sucesora explícita.

3. **Resolver el scope candidato.**

   ```bash
   oguard intent-scan
   ```

   Imprime `Scanned N candidate files`. El scan compara los globs sólo contra archivos observables por Git (trackeados más no trackeados no ignorados) y lista los candidatos de test por separado. No interpreta semántica ni concede preflight.

4. **Revisar el borrador antes de congelarlo.**

   ```bash
   oguard intent-status --json
   ```

   Muestra el borrador, su hash y si el contrato está `not-configured`, `placeholder` o `typed`. Si el scope resolvió a los archivos equivocados, volvé a correr `oguard intent` con globs corregidos y reescaneá. Iterar acá es gratis; iterar después de congelar el contrato no lo es.

5. **Congelar la ronda con checks reproducibles.**

   ```bash
   oguard start --from-intent \
     --round-id R-1 --round "Add checkout regression coverage" \
     --kr-id KR-1 --kr "Checkout has a regression test" \
     --check test=npm,run,test --check-timeout-ms 900000 \
     --criterion-id C-1 --criterion "Checkout behavior and compatibility pass" \
     --criterion-checks test \
     --obligation behavior=C-1 --obligation compatibility=C-1
   ```

   `--from-intent` copia objetivo, tipo de tarea y scope desde el borrador ya revisado; ronda y key result se pasan acá. `start` escribe el contrato tipado, siempre incluye `oguard.contract.json` en el scope y congela una instantánea inmutable en `.oguard/session-baseline.json`. Se niega a una segunda invocación: las sucesoras pasan por `next-round`.

   Los flags de check, criterio y obligación importan en una ronda `feature`. Una `feature` exige obligaciones `behavior` y `compatibility` respaldadas por criterios que referencien checks declarados. Si los omitís, `start` imprime `W criterion-checks — …`; entonces la ronda sólo puede cerrar con esas obligaciones en `unknown`, y una ronda congelada no se puede enmendar: los resultados de pruebas corridas a mano nunca se acreditan retroactivamente. En ese caso el remedio es una ronda sucesora con los checks declarados, no editar la evidencia de la ronda actual.

   `--check test=npm,run,test` declara el argv `npm run test`. Como eso coincide con lo que el planner descubre desde `package.json`, el candidato descubierto se deduplica en lugar de reportarse como recomendación no configurada.

6. **Commitear el contrato.**

   ```bash
   git add oguard.contract.json && git commit -m "open round R-1"
   ```

   `oguard.contract.json` (y `oguard.plan.json`, `oguard.kpis.json` cuando se usan) son artefactos de tarea versionados. `.oguard/` es estado operativo local append-only; agregalo a `.gitignore`.

7. **Correr el preflight antes de la primera edición material.**

   ```bash
   oguard task-flow --json
   ```

   `status: "ready"` resume objetivo, ronda, tipo de tarea, contexto de trabajo, scope, non-goals, estado del baseline, salud de gobernanza y validación de KPIs, y registra una autorización de preflight ligada al hash del contrato y al hash de la política de KPIs por una hora. `action-required` termina con código no cero e indica qué resolver primero. Un repositorio nuevo no tiene `oguard.kpis.json`, así que los KPIs reportan `not-configured`; versionar ese archivo hace que la política de KPIs forme parte del preflight.

8. **Hacer la edición dentro del scope.** Por ejemplo, agregar `test/checkout.test.mjs` y modificar `src/checkout.mjs`.

9. **Chequear el archivo editado.**

   ```bash
   oguard check --file test/checkout.test.mjs
   ```

   Aplica los cuatro detectores universales a las líneas agregadas de ese archivo. Imprime sólo los hallazgos nuevos (como máximo cinco, luego un conteo) más la cantidad de resueltos, y termina con 1 cuando algún hallazgo tiene severidad `error`: un test deshabilitado, un stub en producción o un error de sintaxis. Una dependencia nueva es `warning` y no cambia el código de salida.

10. **Chequear la alineación contra el contrato.**

    ```bash
    oguard align
    ```

    Reimprime objetivo y ronda, la superficie de cambio (`files / churn / modules / outside scope`), los conteos de evidencia por key result y como máximo una advertencia de alineación. El código de salida sigue siendo 0 incluso cuando advierte. Un path tocado es evidencia candidata, nunca prueba de que un key result esté logrado.

11. **Cerrar la ronda.**

    ```bash
    oguard round-end
    ```

    El modo `fast` por defecto corre los detectores universales sobre cada archivo fuente modificado, los checks declarados con alcance `fast` (o sin modo), `git diff --check`, y luego evalúa criterios y obligaciones. Leé la última línea: `[round-end] STATUS — N changed source files; verification=…; evidence=…`. `pass` significa que los checks en scope no encontraron violación; `warn`, que hay un hallazgo activo o una advertencia de alineación efectiva; `block`, una falla determinista o un criterio requerido violado; `unknown`, que la evidencia fue insuficiente para concluir.

12. **Cerrar con el gate final.**

    ```bash
    oguard round-end --mode final
    ```

    Selecciona los checks declarados para `final` (o sin modo) y bloquea cuando algún criterio requerido sigue en `unknown`. Este es el modo que responde si la ronda es promocionable.

13. **Exportar la evidencia.**

    ```bash
    oguard evidence export --output evidence/runs/first-round.json
    ```

    Escribe el artefacto de evidencia sanitizado. La ruta de salida debe coincidir con `evidence/runs/*.json`; cualquier otra ubicación se rechaza. Opcionalmente registrá después la adjudicación humana con `oguard outcome --outcome confirmed-correct --note "Reviewed against expected behavior"`, que agrega un evento sin cambiar el veredicto registrado.

## Qué verificó el guard — y qué no

- `pass` significa únicamente que los checks en scope no encontraron violación. No es evidencia de que el objetivo se haya logrado, de que el cambio sea correcto ni de que el guard haya sido útil.
- Un check candidato omitido nunca amplía un `pass`. Queda `skipped`, y el cierre reporta `verification: "incomplete"` con los nombres omitidos. Dos razones son sólo informativas y no degradan el veredicto: `discovered-not-configured` (un script de `package.json` que el planner encontró pero nunca autorizaste) y `workspace-affected-not-configured`.
- `unknown` significa evidencia insuficiente, no falla. En modo `fast`, un criterio requerido en `unknown` mantiene el veredicto en `unknown`; la obligación de regresión de `bugfix` bloquea incluso en `fast`. En modo `final`, todo criterio requerido en `unknown` bloquea.
- Las obligaciones nunca se infieren. Una obligación de `feature` queda `proven` sólo cuando todos los criterios que referencia fueron probados por un check declarado; paths, texto del objetivo y juicio del modelo no cuentan.
- La alineación cuenta paths, no significado. Los archivos de contabilidad (`oguard.contract.json`, `oguard.plan.json`, `oguard.kpis.json`, `.oguard/**`) nunca acreditan por sí mismos un key result, y un glob que resuelve sólo a archivos ignorados emite `scope-unobservable`.
- La cobertura de los detectores es acotada por diseño. La verificación de sintaxis cubre sólo `.js`, `.mjs` y `.cjs`; los archivos TypeScript, JSX y Java se miden como superficie pero no se chequean sintácticamente.
- La telemetría prueba uso, no beneficio. `oguard inventory dashboard` declara explícitamente `causal_effect: not-evaluable`: el volumen de uso y una corrección posterior no atribuyen al guard una deriva evitada, tiempo ahorrado ni tokens ahorrados.
- El gate pre-edición es fail-open. Los repositorios sin contrato tipado no se bloquean, y el gate no intenta clasificar escrituras arbitrarias dentro de comandos de shell. Esa cobertura parcial se declara en lugar de presentarse como aislamiento.

## Trabajar dentro de un harness de agentes

Dentro de un harness de agentes de programación el flujo anterior se hace cumplir en lugar de recordarse. El prompt del harness inyecta `oguard task-flow` al inicio de cada pedido, y un hook global `PreToolUse` sobre las herramientas estructuradas `Edit` y `Write` ejecuta el gate local. El gate permite la edición sólo cuando el último `task-flow: ready` coincide con el hash actual del contrato y con el hash de la política de KPIs y tiene menos de una hora; en caso contrario la llamada a la herramienta recibe `permissionDecision: deny` con el comando a ejecutar. Editar mediante comandos de shell queda fuera de su cobertura. La variable de entorno `OGUARD_HARNESS` etiqueta qué harness produjo cada evento de telemetría.

La configuración por harness está en las guías correspondientes:

- [Panorama de guías por harness](guides/README.es.md)
- [Claude Code](guides/claude-code.es.md)
- [Codex](guides/codex.es.md)

## Referencia de comandos

`oguard --help` imprime el uso completo. Todos los comandos de abajo están verificados contra `src/cli.mjs`.

### Configuración e intención

| Comando | Qué hace | Cuándo lo necesitás |
| --- | --- | --- |
| `init` | Crea `oguard.contract.json` en modo `observe` con un objetivo placeholder; se niega a sobrescribir. | Una vez por repositorio, antes que todo lo demás. |
| `intent --objective-id --objective --task-type --scope` | Guarda un borrador local revisable en `.oguard/intent.json`. | Antes de congelar un contrato, mientras objetivo o scope siguen siendo una hipótesis. |
| `intent-scan` | Resuelve los globs del borrador contra archivos observables por Git y lista candidatos de test. | Para confirmar que el scope candidato resuelve a los archivos que pretendías. |
| `intent-status` | Reporta si existe un borrador local y si el contrato está ausente, en placeholder o tipado. | Para revisar el borrador antes de promoverlo. |
| `start … [--from-intent]` | Convierte el placeholder en una ronda tipada y congela `.oguard/session-baseline.json`. | Una vez por repositorio; después usá `next-round`. |
| `plan-template` | Imprime el `oguard.plan.json` mínimo derivado del contrato tipado. | Cuando querés un plan versionado fuera del contrato de ronda. |
| `anchor-plan` | Ancla un `oguard.plan.json` ya commiteado en el baseline activo. | Después de commitear el plan, con árbol limpio. |

### Ciclo de vida de la ronda

| Comando | Qué hace | Cuándo lo necesitás |
| --- | --- | --- |
| `task-flow [--json]` | Verifica contrato tipado, coincidencia de baseline, salud de gobernanza y política de KPIs; concede un preflight de una hora o termina con código no cero. | Antes de la primera edición material de cada pedido. |
| `next-round …` | Abre una ronda sucesora tipada archivando el contrato y baseline previos bajo `.oguard/history/`. | Antes de trabajo nuevo, con árbol limpio y baseline coincidente. |
| `adopt-baseline` | Crea el primer baseline para un contrato tipado histórico que no lo tiene. | Sólo como migración única; las transiciones normales usan `next-round`. |
| `register-plan-amendment` | Archiva el contenido actual del plan y registra la enmienda antes de que lo edites. | Antes de cambiar un `oguard.plan.json` anclado. |

### Verificación

| Comando | Qué hace | Cuándo lo necesitás |
| --- | --- | --- |
| `check --file <path>` | Corre los cuatro detectores universales sobre las líneas agregadas de un archivo; termina con 1 ante un hallazgo `error`. | Después de cada edición material. |
| `align` | Reporta objetivo, ronda, superficie de cambio, evidencia por key result y advertencias de alineación; siempre termina con 0. | Después de un parche, para ver deriva antes de cerrar. |
| `round-end [--mode fast\|final]` | Corre detectores sobre archivos modificados, los checks declarados del modo, `git diff --check`, criterios y obligaciones; termina con 1 en `block`. | Para cerrar una ronda; `final` decide la promocionabilidad. |

### Hallazgos, adjudicación y gobernanza

| Comando | Qué hace | Cuándo lo necesitás |
| --- | --- | --- |
| `list` | Imprime los hallazgos activos guardados en `.oguard/state.json`. | Para ver el detalle completo detrás de un `check` truncado. |
| `label <finding-id> --outcome` | Etiqueta un hallazgo como `true-positive`, `false-positive` o `unclear`. | Cuando construís datos de calibración a partir de hallazgos reales. |
| `outcome --outcome --note` | Registra un veredicto humano para la última ronda cerrada sin alterarla. | Después de revisar una ronda cerrada. |
| `health` | Consolida hash del plan, enmiendas, integridad y hallazgos activos/resueltos. Implementado pero ausente del `--help`. | Para inspeccionar la salud de gobernanza por separado. |
| `reset` | Descarta el estado local de hallazgos. | Sólo después de revisar `.oguard/state.json`. |

### Evidencia

| Comando | Qué hace | Cuándo lo necesitás |
| --- | --- | --- |
| `evidence` | Imprime un resumen de rondas, clasificaciones, etiquetas y hallazgos sin etiquetar. | Para un estado local rápido. |
| `evidence export --output evidence/runs/<nombre>.json` | Escribe el artefacto de evidencia sanitizado de las rondas registradas. | Al final de una ronda. |
| `evidence report --output evidence/runs/<nombre>.json` | Escribe el reporte pasivo, incluyendo los outcomes registrados. | Para revisión o handoff. |
| `evidence dataset calibration\|evaluation --output evidence/runs/<nombre>.json` | Escribe un dataset pasivo y separado con features versionadas. | Para trabajo de calibración offline; no activa umbrales. |

### Telemetría y KPIs

| Comando | Qué hace | Cuándo lo necesitás |
| --- | --- | --- |
| `inventory discover [--root <path>]` | Lista proyectos Git bajo la raíz indicada con su último evento del guard. | Para ver dónde está instalado el guard. Pasá `--root`: los valores por defecto son rutas absolutas de la máquina del autor. |
| `inventory status` | Reporta el estado del inventario global. | Para confirmar que la telemetría se está escribiendo. |
| `inventory report` | Agrega los eventos globales sanitizados, incluidos los totales de `pre_edit`. | Para revisar adopción sin leer eventos crudos. |
| `inventory kpis [--policy <file>]` | Deriva cobertura de preflight, tasa de denegación, p95 de latencia y resolución de hallazgos; valida umbrales y termina con 1 ante una violación bloqueante. | Para hacer cumplir una política de KPIs local o en CI. |
| `inventory dashboard [--days N]` | Agrega adopción, disciplina de flujo, intervención y resolución por proyecto y harness. | Para una vista general de uso; declara `causal_effect: not-evaluable`. |

### Excepciones y recuperación

| Comando | Qué hace | Cuándo lo necesitás |
| --- | --- | --- |
| `reanchor-baseline --reason <text>` | Mueve el baseline a un contrato modificado después de una ronda que pasó. | Sólo después de un `round-end` con `pass` para el contrato actual. |
| `accept-baseline --reason <text> --actor <text>` | Registra una aceptación local explícita de deuda no promocionable, conservando el estado fallido o desconocido. | Cuando un responsable acepta el resultado de una ronda cerrada para desbloquear trabajo posterior. |

Las excepciones auditables a advertencias de política se declaran en el arreglo `exceptions[]` del contrato (`id`, `rule`, `reason`, `actor`, un `expires_at` futuro y `scope.paths` no vacío), no mediante un comando del CLI. `round-end` conserva la advertencia original y registra `exception-applied` por separado.

## Próximos pasos

- [Índice de documentación](README.es.md)
- [Visión y tesis](product/01-vision-and-thesis.es.md)
- [Contrato de producto](product/02-product-contract.es.md)
- [Mapa funcional](functionality/INDEX.es.md)
- [Episodios y hallazgos](episodes/README.es.md)
- [Guías por harness](guides/README.es.md)
