chore: bootstrap agnostic agent harness framework

This commit is contained in:
rikrdo
2026-05-03 17:46:19 +02:00
commit 1597b18a30
23 changed files with 809 additions and 0 deletions

19
AGENTS.md Normal file
View File

@@ -0,0 +1,19 @@
# AGENTS.md — Entry point del framework
## Arranque obligatorio
1. Leer `work/current.md`.
2. Leer `backlog/features.json` y seleccionar **una** feature `pending`.
3. Ejecutar `./scripts/verify.sh`.
4. Seguir `harness/workflow.stages.yml` y `harness/agents.matrix.yml`.
## Reglas duras
- Una sola feature en `in_progress`.
- Ningún agente pasa código por chat: todo va a `work/artifacts/<feature_id>/`.
- `implementer` nunca marca `done`.
- `done` requiere gates aprobados: `reviewer`, `security`, `qa`.
- Si `verify.sh` falla, no se cierra la feature.
## Reentrada (context loss)
- Releer `work/current.md` y artefactos de la feature activa.
- Ejecutar `./scripts/verify.sh`.
- Continuar desde “Próximo paso”.

21
CHECKPOINTS.md Normal file
View File

@@ -0,0 +1,21 @@
# CHECKPOINTS
## C1 — Estructura
- [ ] Existe `harness/`, `spec/`, `backlog/`, `work/`, `scripts/`, `platforms/`.
## C2 — Estado
- [ ] Máximo una feature en `in_progress`.
- [ ] Estados válidos en backlog.
## C3 — Gates
- [ ] Toda feature `done` tiene `reviewer.json` aprobado.
- [ ] Toda feature `done` tiene `security.json` aprobado.
- [ ] Toda feature `done` tiene `qa.json` aprobado.
- [ ] Toda feature `done` tiene `leader-close.json` válido.
## C4 — Verificación
- [ ] `./scripts/verify.sh` termina en OK.
## C5 — Trazabilidad
- [ ] `work/history.md` actualizado en cierre.
- [ ] Artefactos por feature en `work/artifacts/<feature_id>/`.

145
HOWTO.md Normal file
View File

@@ -0,0 +1,145 @@
# HOWTO — Cómo usar ARNES Framework
Guía rápida para arrancar proyectos nuevos usando este framework.
---
## Fórmula base (siempre igual)
1. **Crear repo nuevo**
2. **Copiar ARNES Framework dentro del repo**
3. **Configurar spec + backlog**
4. **Ejecutar verificación**
5. **Empezar implementación por features (una a la vez)**
---
## 1) Crear repo
```bash
mkdir mi-proyecto
cd mi-proyecto
git init
```
---
## 2) Copiar framework
Desde tu copia local de ARNES:
```bash
cp -R /ruta/a/arnes/* .
cp -R /ruta/a/arnes/.[!.]* . 2>/dev/null || true
```
> Si usas plantilla remota, clónala y copia su contenido al repo nuevo.
---
## 3) Personalizar proyecto
Edita mínimo:
- `README.md` (contexto del proyecto)
- `spec/product.md` (qué construir)
- `spec/tech.md` (stack y límites técnicos)
- `spec/acceptance.md` (criterios de aceptación)
- `backlog/features.json` (features iniciales en `pending`)
- `harness/agents.matrix.yml` (roles/permisos)
- `harness/workflow.stages.yml` (flujo y gates)
---
## 4) Elegir plataforma (pi.dev u opencode)
Usa el adaptador correspondiente:
- `platforms/pi/`
- `platforms/opencode/`
El núcleo del framework no cambia; solo cambian prompts/hooks/permisos de plataforma.
---
## 5) Inicializar estado de trabajo
Verifica que existan y estén limpios:
- `work/current.md`
- `work/history.md`
- `work/artifacts/`
Pon solo **1 feature activa** (`in_progress`) como máximo.
---
## 6) Ejecutar verificación inicial
```bash
./scripts/verify.sh
```
Si falla, **no empezar implementación** hasta dejar todo en verde.
---
## 7) Ciclo operativo por feature
Orden obligatorio:
1. `leader` orquesta
2. `architect` define/ajusta diseño
3. `implementer` implementa + tests
4. `reviewer` gate técnico
5. `security` gate seguridad
6. `qa` gate funcional
7. `leader` cierra si todo está aprobado
Reglas clave:
- una feature a la vez
- evidencia en disco (`work/artifacts/<feature>/...`)
- nadie marca `done` si falta un gate
---
## 8) Cierre de feature
Antes de pasar a `done`:
- `verify.sh` en verde
- review aprobado
- security aprobado
- qa aprobado
- resumen en `work/history.md`
---
## 9) Manejo de pérdida de contexto (memoria)
Si una sesión se corta:
1. leer `work/current.md`
2. revisar `backlog/features.json`
3. abrir artefactos de la feature activa
4. ejecutar `./scripts/verify.sh`
5. continuar desde “Próximo paso”
---
## 10) Checklist rápido de arranque
- [ ] Repo creado
- [ ] Framework copiado
- [ ] Specs escritas
- [ ] Backlog definido
- [ ] Matriz de agentes configurada
- [ ] Workflow de stages configurado
- [ ] Verificación inicial OK
- [ ] Primera feature en `pending`
---
## Comando mental (resumen)
**Crear repo → copiar framework → definir spec/backlog → verificar → ejecutar pipeline de 6 agentes con gates obligatorios.**

170
README.md Normal file
View File

@@ -0,0 +1,170 @@
# ARNES Framework (agnóstico) — Diseño v0.1
Framework para construir aplicaciones con agentes autónomos, con control estricto de calidad, seguridad y trazabilidad.
Compatible por diseño con **pi.dev** y **opencode** mediante adaptadores.
---
## Objetivo
Permitir que agentes implementen features de forma autónoma **sin perder control**:
- una feature a la vez
- evidencia en disco (no en chat)
- gates obligatorios de revisión, seguridad y QA
- cierre solo con validación completa
---
## Principios
1. **Vendor-neutral**: núcleo independiente de herramienta.
2. **Estado persistente**: todo vive en archivos versionables.
3. **No confianza ciega**: “funciona” debe demostrarse con evidencia ejecutable.
4. **Separación de roles**: quien implementa no aprueba.
5. **Anti-trampa por diseño**: no se puede marcar `done` saltando gates.
---
## Matriz de agentes (6)
1. **leader**
- Orquesta etapas y handoffs.
- No implementa código de producto.
2. **architect**
- Define/ajusta diseño técnico y contratos.
- Puede editar documentación y diseño.
3. **implementer**
- Implementa una sola feature + tests.
- No puede aprobar ni cerrar.
4. **reviewer**
- Revisión técnica vs arquitectura/convenios.
- No edita código, solo aprueba/rechaza.
5. **security**
- Gate de seguridad: secretos, dependencias, SAST básico, hardening checks.
- No edita código.
6. **qa**
- Gate de calidad funcional: aceptación, integración/E2E, regresión.
- No edita código.
---
## Flujo de trabajo (pipeline)
1. `intake` (leader)
2. `design` (architect)
3. `build` (implementer)
4. `review_gate` (reviewer) ✅
5. `security_gate` (security) ✅
6. `qa_gate` (qa) ✅
7. `close` (leader)
**Regla:** no hay `done` si cualquier gate falla.
---
## Anti-trampa (control estricto)
### Reglas de autorización
- Solo `leader` puede mover `in_progress -> done`.
- `implementer` no puede editar archivos de estado final de cierre.
- `reviewer/security/qa` no pueden editar código de producto.
### Evidencia obligatoria por etapa
Cada agente escribe artefactos en disco:
- `work/artifacts/<feature>/implementer.md`
- `work/artifacts/<feature>/reviewer.md`
- `work/artifacts/<feature>/security.md`
- `work/artifacts/<feature>/qa.md`
Respuesta de agente siempre: `done -> <ruta>` o `blocked -> <ruta>`.
### Gates ejecutados fuera del agente
- Verificación disparada por harness/scripts (no por “declaración” del agente).
- Si gate falla, estado vuelve a `blocked` o permanece `in_progress`.
### Trazabilidad y auditoría
- `work/history.md` append-only.
- Checklist de cierre firmado por etapa (aprobado/rechazado + evidencia).
- Cualquier missing evidence = cierre denegado.
---
## Estructura propuesta
```text
.
├── README.md
├── harness/
│ ├── agents.matrix.yml
│ ├── workflow.stages.yml
│ ├── policies/
│ │ ├── security.md
│ │ ├── quality.md
│ │ └── governance.md
│ └── contracts/
│ ├── handoff.md
│ └── evidence.schema.json
├── spec/
│ ├── product.md
│ ├── tech.md
│ └── acceptance.md
├── backlog/
│ └── features.json
├── work/
│ ├── current.md
│ ├── history.md
│ └── artifacts/
└── scripts/
└── verify.sh
```
---
## Manejo de pérdidas de memoria (context loss)
Sí: el framework está diseñado para eso.
Mecanismos:
1. **Estado en disco** (`work/current.md`, `backlog/features.json`).
2. **Bitácora append-only** (`work/history.md`).
3. **Handoffs explícitos** por archivo, no por chat.
4. **Protocolo de reentrada** al iniciar sesión:
- leer `work/current.md`
- leer feature activa
- ejecutar verificación base
- continuar desde “próximo paso”
Si se pierde contexto del modelo, el sistema se puede reconstruir desde archivos.
---
## Adaptadores de plataforma
- `platforms/pi/`: prompts, hooks, permisos, comandos compatibles con pi.dev.
- `platforms/opencode/`: prompts, hooks, permisos, comandos compatibles con opencode.
El núcleo no cambia; solo el adaptador.
---
## Criterios de éxito del framework
- No se puede cerrar una feature sin 3 gates en verde (review/security/qa).
- Evidencia completa y auditable por feature.
- Reentrada robusta tras reinicio o pérdida de contexto.
- Portabilidad entre pi.dev y opencode sin rediseñar el núcleo.
---
## Próximos pasos sugeridos
1. Definir `agents.matrix.yml` completo (permisos exactos por rutas).
2. Definir `workflow.stages.yml` con transiciones válidas.
3. Diseñar `features.json` con estados y criterios de aceptación.
4. Especificar `scripts/verify.sh` (lint/test/security/qa gates).
5. Crear adaptadores `platforms/pi` y `platforms/opencode`.

24
backlog/features.json Normal file
View File

@@ -0,0 +1,24 @@
{
"project": "nuevo-proyecto",
"description": "Backlog inicial del proyecto",
"rules": {
"one_feature_at_a_time": true,
"require_review_gate": true,
"require_security_gate": true,
"require_qa_gate": true,
"valid_status": ["pending", "in_progress", "blocked", "done"]
},
"features": [
{
"id": "F-001",
"title": "Definir estructura inicial",
"description": "Bootstrap del proyecto con estructura base.",
"acceptance": [
"Estructura base creada",
"Tests o checks iniciales definidos",
"Artefactos de gate configurados"
],
"status": "pending"
}
]
}

63
harness/agents.matrix.yml Normal file
View File

@@ -0,0 +1,63 @@
version: 1
roles:
leader:
can_edit: ["work/", "backlog/", "spec/", "harness/"]
cannot_edit: ["src/", "tests/"]
responsibilities:
- plan
- orchestrate
- enforce_gates
- close_feature
architect:
can_edit: ["spec/", "harness/contracts/", "docs/"]
cannot_edit: ["src/", "tests/", "backlog/features.json:status"]
responsibilities:
- design
- update_contracts
implementer:
can_edit: ["src/", "tests/", "work/artifacts/"]
cannot_edit:
- "backlog/features.json:done"
- "work/history.md"
- "work/artifacts/*/reviewer.json"
- "work/artifacts/*/security.json"
- "work/artifacts/*/qa.json"
- "work/artifacts/*/leader-close.json"
responsibilities:
- implement_feature
- write_tests
- produce_implementer_evidence
reviewer:
can_edit: ["work/artifacts/"]
cannot_edit: ["src/", "tests/", "backlog/"]
responsibilities:
- technical_review
- emit_reviewer_verdict
security:
can_edit: ["work/artifacts/"]
cannot_edit: ["src/", "tests/", "backlog/"]
responsibilities:
- sast
- dependency_review
- secret_scan
- emit_security_verdict
qa:
can_edit: ["work/artifacts/"]
cannot_edit: ["src/", "tests/", "backlog/"]
responsibilities:
- acceptance_traceability
- integration_e2e_checks
- regression_checks
- emit_qa_verdict
anti_cheat:
- "Implementer cannot promote feature to done"
- "Done requires reviewer/security/qa approved artifacts"
- "Leader close requires verify.sh success"
- "Evidence must be on disk; chat-only claims are invalid"

View File

@@ -0,0 +1,19 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://arnes.local/evidence.schema.json",
"title": "Gate Evidence",
"type": "object",
"required": ["feature_id", "agent", "verdict", "summary", "evidence", "timestamp"],
"properties": {
"feature_id": { "type": "string", "minLength": 1 },
"agent": { "type": "string", "enum": ["reviewer", "security", "qa", "leader"] },
"verdict": { "type": "string", "enum": ["APPROVED", "CHANGES_REQUESTED"] },
"summary": { "type": "string", "minLength": 1 },
"evidence": {
"type": "array",
"items": { "type": "string", "minLength": 1 }
},
"timestamp": { "type": "string", "format": "date-time" }
},
"additionalProperties": true
}

View File

@@ -0,0 +1,21 @@
# Handoff Contract
## Regla anti teléfono-descompuesto
Los agentes **no** devuelven código en chat. Deben escribir a disco y responder solo:
- `done -> <ruta>`
- `blocked -> <ruta>`
## Rutas estándar por feature
- `work/artifacts/<feature_id>/implementer.md`
- `work/artifacts/<feature_id>/reviewer.json`
- `work/artifacts/<feature_id>/security.json`
- `work/artifacts/<feature_id>/qa.json`
- `work/artifacts/<feature_id>/leader-close.json`
## Campos mínimos de artefactos JSON de gate
- `feature_id` (string)
- `agent` (reviewer|security|qa|leader)
- `verdict` (APPROVED|CHANGES_REQUESTED)
- `summary` (string)
- `evidence` (array de comandos/salidas/rutas)
- `timestamp` (ISO 8601)

View File

@@ -0,0 +1,16 @@
# Governance Policy
## Reglas
- Una sola feature activa (`in_progress`) a la vez.
- El pipeline es secuencial con gates obligatorios.
- `done` solo por `leader` y solo con evidencia completa.
## Separación de funciones
- Implementer construye.
- Reviewer/Security/QA validan.
- Leader decide cierre.
## Prohibiciones
- Saltar gates.
- Aprobar con evidencia incompleta.
- Cerrar con `verify.sh` en rojo.

View File

@@ -0,0 +1,12 @@
# Quality Policy
## Gate QA (obligatorio)
Cada feature debe tener `work/artifacts/<feature_id>/qa.json` con:
- `verdict`: APPROVED | CHANGES_REQUESTED
- trazabilidad criterio de aceptación -> test
- resultado de pruebas integración/E2E relevantes
## Reglas
- No hay `done` sin cobertura mínima de acceptance.
- No hay `done` con regresiones abiertas.
- Claims sin evidencia ejecutable no son válidos.

View File

@@ -0,0 +1,12 @@
# Security Policy
## Gate de seguridad (obligatorio)
Cada feature debe tener `work/artifacts/<feature_id>/security.json` con:
- `verdict`: APPROVED | CHANGES_REQUESTED
- `checks`: secretos, dependencias, SAST básico, validación de inputs
- `findings`: lista de hallazgos con severidad
## Reglas
- Si hay hallazgos críticos/altos sin mitigación: `CHANGES_REQUESTED`.
- No se permite exponer credenciales ni secretos en repo/chat.
- Dependencias nuevas requieren justificación en `spec/tech.md`.

View File

@@ -0,0 +1,55 @@
version: 1
feature_states:
allowed: [pending, in_progress, blocked, done]
stages:
- name: intake
owner: leader
input:
- backlog/features.json
- work/current.md
output:
- work/current.md
- name: design
owner: architect
optional: true
output:
- work/artifacts/<feature_id>/architect.md
- name: build
owner: implementer
output:
- work/artifacts/<feature_id>/implementer.md
- name: review_gate
owner: reviewer
required: true
output:
- work/artifacts/<feature_id>/reviewer.json
- name: security_gate
owner: security
required: true
output:
- work/artifacts/<feature_id>/security.json
- name: qa_gate
owner: qa
required: true
output:
- work/artifacts/<feature_id>/qa.json
- name: close
owner: leader
required: true
output:
- work/artifacts/<feature_id>/leader-close.json
- work/history.md
close_requirements:
- reviewer.json.verdict == "APPROVED"
- security.json.verdict == "APPROVED"
- qa.json.verdict == "APPROVED"
- scripts/verify.sh exit_code == 0

View File

@@ -0,0 +1,13 @@
# Adaptador opencode
Usa este adaptador para ejecutar ARNES en opencode.
## Recomendado
- Definir perfiles/roles con la matriz `harness/agents.matrix.yml`.
- Separar permisos por rutas para evitar bypass de gates.
- Forzar handoff por archivos (`work/artifacts/<feature_id>/`).
- Ejecutar `./scripts/verify.sh` en pre-close.
## Respuesta estándar de subagentes
- `done -> <ruta>`
- `blocked -> <ruta>`

View File

@@ -0,0 +1,4 @@
Rol: leader.
No escribas código de producto.
Coordina intake -> design -> build -> review_gate -> security_gate -> qa_gate -> close.
Si falta evidencia en disco o falla verify.sh, no cerrar feature.

13
platforms/pi/README.md Normal file
View File

@@ -0,0 +1,13 @@
# Adaptador pi.dev
Usa este adaptador para ejecutar ARNES en pi.dev.
## Recomendado
- Cargar `AGENTS.md` como entrada principal.
- Enforzar roles según `harness/agents.matrix.yml`.
- Exigir que subagentes escriban artefactos en `work/artifacts/<feature_id>/`.
- Ejecutar `./scripts/verify.sh` al inicio y antes de cierre.
## Respuesta estándar de subagentes
- `done -> <ruta>`
- `blocked -> <ruta>`

View File

@@ -0,0 +1,5 @@
Actúa como `leader`.
No implementes código de producto.
Orquesta stages según `harness/workflow.stages.yml`.
Aplica anti-trampa de `harness/agents.matrix.yml`.
No marques `done` sin gates APPROVED y `./scripts/verify.sh` en verde.

137
scripts/verify.sh Executable file
View File

@@ -0,0 +1,137 @@
#!/usr/bin/env bash
set -u
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[0;33m'
NC='\033[0m'
ok() { printf "${GREEN}[OK]${NC} %s\n" "$1"; }
warn() { printf "${YELLOW}[WARN]${NC} %s\n" "$1"; }
fail() { printf "${RED}[FAIL]${NC} %s\n" "$1"; }
EXIT_CODE=0
echo "── 1) Verificando estructura base ─────────────────────"
required=(
"AGENTS.md"
"CHECKPOINTS.md"
"harness/agents.matrix.yml"
"harness/workflow.stages.yml"
"harness/policies/governance.md"
"harness/policies/security.md"
"harness/policies/quality.md"
"harness/contracts/handoff.md"
"harness/contracts/evidence.schema.json"
"spec/product.md"
"spec/tech.md"
"spec/acceptance.md"
"backlog/features.json"
"work/current.md"
"work/history.md"
)
for f in "${required[@]}"; do
if [ -f "$f" ]; then
ok "Existe $f"
else
fail "Falta $f"
EXIT_CODE=1
fi
done
echo ""
echo "── 2) Validando backlog + gates ───────────────────────"
python3 - <<'PY'
import json
import pathlib
import sys
root = pathlib.Path('.')
path = root / 'backlog' / 'features.json'
try:
data = json.loads(path.read_text(encoding='utf-8'))
except Exception as e:
print(f"[FAIL] backlog/features.json inválido: {e}")
sys.exit(1)
valid = set(data.get('rules', {}).get('valid_status', ["pending", "in_progress", "blocked", "done"]))
features = data.get('features', [])
if not isinstance(features, list):
print('[FAIL] features debe ser una lista')
sys.exit(1)
in_progress = [f for f in features if f.get('status') == 'in_progress']
if len(in_progress) > 1:
print(f"[FAIL] Hay {len(in_progress)} features in_progress (máximo 1)")
sys.exit(1)
for f in features:
fid = str(f.get('id', '')).strip()
status = f.get('status')
if status not in valid:
print(f"[FAIL] Estado inválido en feature {fid}: {status}")
sys.exit(1)
if status == 'done':
d = root / 'work' / 'artifacts' / fid
req = ['reviewer.json', 'security.json', 'qa.json', 'leader-close.json']
missing = [name for name in req if not (d / name).is_file()]
if missing:
print(f"[FAIL] Feature {fid} done sin artefactos: {', '.join(missing)}")
sys.exit(1)
expected = {
'reviewer.json': 'reviewer',
'security.json': 'security',
'qa.json': 'qa',
'leader-close.json': 'leader',
}
for filename, agent in expected.items():
try:
obj = json.loads((d / filename).read_text(encoding='utf-8'))
except Exception as e:
print(f"[FAIL] {fid}/{filename} inválido: {e}")
sys.exit(1)
if obj.get('agent') != agent:
print(f"[FAIL] {fid}/{filename} agent debe ser '{agent}'")
sys.exit(1)
if obj.get('verdict') != 'APPROVED':
print(f"[FAIL] {fid}/{filename} no está APPROVED")
sys.exit(1)
print(f"[OK] backlog válido ({len(features)} features)")
PY
if [ $? -ne 0 ]; then EXIT_CODE=1; fi
echo ""
echo "── 3) Verificación de tests/build (opcional auto-detect) ─"
if [ -f "Makefile" ] && grep -qE '^test:' Makefile; then
if make test; then ok "make test OK"; else fail "make test falló"; EXIT_CODE=1; fi
elif [ -f "package.json" ]; then
if command -v npm >/dev/null 2>&1; then
if npm test --silent --if-present; then ok "npm test OK"; else fail "npm test falló"; EXIT_CODE=1; fi
else
warn "package.json detectado pero npm no está disponible"
fi
elif [ -d "tests" ]; then
if command -v pytest >/dev/null 2>&1; then
if pytest -q; then ok "pytest OK"; else fail "pytest falló"; EXIT_CODE=1; fi
else
if python3 -m unittest discover -s tests -v; then ok "unittest OK"; else fail "unittest falló"; EXIT_CODE=1; fi
fi
else
warn "No se detectó suite automática (tests/ | Makefile test | package.json test)"
fi
echo ""
echo "── 4) Resumen ─────────────────────────────────────────"
if [ $EXIT_CODE -eq 0 ]; then
ok "Harness verificado. Puedes trabajar."
else
fail "Harness NO verificado. Corrige antes de continuar."
fi
exit $EXIT_CODE

9
spec/acceptance.md Normal file
View File

@@ -0,0 +1,9 @@
# Acceptance Criteria
Define criterios verificables por feature.
Formato recomendado:
- Feature ID:
- Escenario:
- Given / When / Then:
- Evidencia esperada (test/comando):

15
spec/product.md Normal file
View File

@@ -0,0 +1,15 @@
# Product Spec
## Problema
Describe el problema de negocio.
## Objetivo
Define el resultado esperado del producto.
## Usuarios
- Usuario principal:
- Usuario secundario:
## Alcance v1
- In scope:
- Out of scope:

19
spec/tech.md Normal file
View File

@@ -0,0 +1,19 @@
# Technical Spec
## Stack
- Lenguaje:
- Framework:
- Runtime:
## Restricciones
- Seguridad:
- Rendimiento:
- Compatibilidad:
## Dependencias
Lista y justificación de dependencias externas.
## Observabilidad
- Logging:
- Métricas:
- Alertas:

0
work/artifacts/.gitkeep Normal file
View File

14
work/current.md Normal file
View File

@@ -0,0 +1,14 @@
# Sesión actual
- Feature en curso: _ninguna_
- Inicio: _—_
- Orquestador: _—_
## Plan
- ...
## Bitácora
- ...
## Próximo paso
- ...

3
work/history.md Normal file
View File

@@ -0,0 +1,3 @@
# Historial (append-only)
> Añadir entradas al final. No reescribir historial previo.