chore(plan): marca Fases H, I y J (Tasks 30-38) completadas

Notas de desviación: Task 31 añade per-file-ignore N999 para pages/* (Streamlit
exige nombres con emoji); se quitan noqa BLE001 inútiles y la var muerta
chosen_example; Task 37 — el build de docker falló por typer 0.12.x vs click
>=8.2, se fijó click<8.2 y el smoke pasó (core healthy /health 200, dashboard
/_stcore/health ok, down limpio). Streamlit verificado con ruff + py_compile.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
Juan
2026-05-11 13:35:28 +02:00
co-authored by Claude Opus 4.7
parent 4efb86c05d
commit 4a8eb34874
+38 -28
View File
@@ -4920,6 +4920,12 @@ git commit -m "feat(api,test): índice de ejecuciones persistido + test resume t
## Phase H — Streamlit Dashboard (Tasks 3035) ## Phase H — Streamlit Dashboard (Tasks 3035)
> Streamlit no se testea con unit tests en este MVP (cost/benefit malo). El smoke manual está documentado en `docs/manual_qa.md` (Task 38). > Streamlit no se testea con unit tests en este MVP (cost/benefit malo). El smoke manual está documentado en `docs/manual_qa.md` (Task 38).
>
> **Nota de implementación (desviación del plan):**
> - **Task 31:** las páginas de Streamlit *deben* llamarse `<n>_<emoji>_<Label>.py` para la navegación multipágina, lo que choca con `N999` de ruff; se añadió `per-file-ignores` para `dashboard/src/agentforge_dashboard/pages/*` en `pyproject.toml` (commit junto a la página de Registro).
> - **Tasks 30-31:** se eliminó el `# noqa: BLE001` del plan (`BLE` no está en `select`, así que `RUF100` lo marcaba como noqa inútil); `diff_view.py` parte el literal HTML largo en dos por legibilidad (E501 está en `ignore`, no era necesario).
> - **Task 32:** se omite la variable muerta `chosen_example` del plan (se asigna directamente a `st.session_state["input_text"]`).
> - Verificación de cada página: `ruff check .` + `python -m py_compile` (no hay unit tests de Streamlit). Los códigos de estado y los nombres de campo se cotejaron contra los modelos del core (`AgentDefinition`, `AgentExecution`, `GuardrailViolation`, `PolicyDefinition`).
### Task 30: Dashboard skeleton — `app.py` y cliente HTTP ### Task 30: Dashboard skeleton — `app.py` y cliente HTTP
@@ -4927,7 +4933,7 @@ git commit -m "feat(api,test): índice de ejecuciones persistido + test resume t
- Create: `dashboard/src/agentforge_dashboard/client.py` - Create: `dashboard/src/agentforge_dashboard/client.py`
- Create: `dashboard/src/agentforge_dashboard/app.py` - Create: `dashboard/src/agentforge_dashboard/app.py`
- [ ] **Step 1: `client.py`** - [x] **Step 1: `client.py`**
```python ```python
"""Cliente HTTP tipado al core. Encapsula httpx y mapea respuestas a dicts.""" """Cliente HTTP tipado al core. Encapsula httpx y mapea respuestas a dicts."""
@@ -5004,7 +5010,7 @@ class CoreClient:
return r.json() return r.json()
``` ```
- [ ] **Step 2: `app.py`** - [x] **Step 2: `app.py`**
```python ```python
"""Entry point del dashboard Streamlit con sidebar de branding y health.""" """Entry point del dashboard Streamlit con sidebar de branding y health."""
@@ -5055,7 +5061,7 @@ if __name__ == "__main__":
main() main()
``` ```
- [ ] **Step 3: Commit** - [x] **Step 3: Commit**
```bash ```bash
git add dashboard/src/agentforge_dashboard/client.py dashboard/src/agentforge_dashboard/app.py git add dashboard/src/agentforge_dashboard/client.py dashboard/src/agentforge_dashboard/app.py
@@ -5070,7 +5076,7 @@ git commit -m "feat(dashboard): scaffolding Streamlit con cliente HTTP y health
- Create: `dashboard/src/agentforge_dashboard/pages/1_🏛️_Registro.py` - Create: `dashboard/src/agentforge_dashboard/pages/1_🏛️_Registro.py`
- Create: `dashboard/src/agentforge_dashboard/components/diff_view.py` - Create: `dashboard/src/agentforge_dashboard/components/diff_view.py`
- [ ] **Step 1: `components/diff_view.py`** - [x] **Step 1: `components/diff_view.py`**
```python ```python
"""Componente para renderizar diffs unificados con coloreado básico.""" """Componente para renderizar diffs unificados con coloreado básico."""
@@ -5097,7 +5103,7 @@ def render_unified_diff(diff_text: str) -> None:
st.markdown(html, unsafe_allow_html=True) st.markdown(html, unsafe_allow_html=True)
``` ```
- [ ] **Step 2: `pages/1_🏛️_Registro.py`** - [x] **Step 2: `pages/1_🏛️_Registro.py`**
```python ```python
"""Página de registro de agentes: lista, detalle, versiones y diff.""" """Página de registro de agentes: lista, detalle, versiones y diff."""
@@ -5161,7 +5167,7 @@ if len(versions) >= 2:
render_unified_diff(diff["unified_diff"]) render_unified_diff(diff["unified_diff"])
``` ```
- [ ] **Step 3: Commit** - [x] **Step 3: Commit**
```bash ```bash
git add dashboard/src/agentforge_dashboard/pages/1_🏛️_Registro.py dashboard/src/agentforge_dashboard/components/diff_view.py git add dashboard/src/agentforge_dashboard/pages/1_🏛️_Registro.py dashboard/src/agentforge_dashboard/components/diff_view.py
@@ -5177,7 +5183,7 @@ git commit -m "feat(dashboard): página de Registro con detalle, versiones y dif
- Create: `dashboard/src/agentforge_dashboard/components/trace_view.py` - Create: `dashboard/src/agentforge_dashboard/components/trace_view.py`
- Create: `dashboard/src/agentforge_dashboard/components/violation_view.py` - Create: `dashboard/src/agentforge_dashboard/components/violation_view.py`
- [ ] **Step 1: `components/trace_view.py`** - [x] **Step 1: `components/trace_view.py`**
```python ```python
"""Renderiza el decision_path como timeline.""" """Renderiza el decision_path como timeline."""
@@ -5205,7 +5211,7 @@ def render_trace(decision_path: list[dict]) -> None:
st.json(step["detail"]) st.json(step["detail"])
``` ```
- [ ] **Step 2: `components/violation_view.py`** - [x] **Step 2: `components/violation_view.py`**
```python ```python
"""Renderiza violaciones de guardrails con badges de severidad.""" """Renderiza violaciones de guardrails con badges de severidad."""
@@ -5236,7 +5242,7 @@ def render_violations(violations: list[dict]) -> None:
st.caption(v["message"]) st.caption(v["message"])
``` ```
- [ ] **Step 3: `pages/2_▶️_Ejecutar.py`** - [x] **Step 3: `pages/2_▶️_Ejecutar.py`**
```python ```python
"""Página para invocar un agente y visualizar la traza completa.""" """Página para invocar un agente y visualizar la traza completa."""
@@ -5314,7 +5320,7 @@ elif execution and "error" in execution:
st.error(f"Error de la API: {execution['error']}") st.error(f"Error de la API: {execution['error']}")
``` ```
- [ ] **Step 4: Commit** - [x] **Step 4: Commit**
```bash ```bash
git add dashboard/src/agentforge_dashboard/pages/2_▶️_Ejecutar.py dashboard/src/agentforge_dashboard/components/trace_view.py dashboard/src/agentforge_dashboard/components/violation_view.py git add dashboard/src/agentforge_dashboard/pages/2_▶️_Ejecutar.py dashboard/src/agentforge_dashboard/components/trace_view.py dashboard/src/agentforge_dashboard/components/violation_view.py
@@ -5328,7 +5334,7 @@ git commit -m "feat(dashboard): página Ejecutar con trace timeline y violations
**Files:** **Files:**
- Create: `dashboard/src/agentforge_dashboard/pages/3_🤝_Aprobaciones.py` - Create: `dashboard/src/agentforge_dashboard/pages/3_🤝_Aprobaciones.py`
- [ ] **Step 1: Implementar** - [x] **Step 1: Implementar**
```python ```python
"""Página de aprobaciones pendientes (HITL).""" """Página de aprobaciones pendientes (HITL)."""
@@ -5416,7 +5422,7 @@ with col_r:
st.rerun() st.rerun()
``` ```
- [ ] **Step 2: Commit** - [x] **Step 2: Commit**
```bash ```bash
git add dashboard/src/agentforge_dashboard/pages/3_🤝_Aprobaciones.py git add dashboard/src/agentforge_dashboard/pages/3_🤝_Aprobaciones.py
@@ -5430,7 +5436,7 @@ git commit -m "feat(dashboard): página Aprobaciones con HITL approve/reject por
**Files:** **Files:**
- Create: `dashboard/src/agentforge_dashboard/pages/4_📜_Historial.py` - Create: `dashboard/src/agentforge_dashboard/pages/4_📜_Historial.py`
- [ ] **Step 1: Implementar** - [x] **Step 1: Implementar**
```python ```python
"""Página de historial de ejecuciones y log de violaciones.""" """Página de historial de ejecuciones y log de violaciones."""
@@ -5487,7 +5493,7 @@ with tabs[1]:
st.dataframe(violations, hide_index=True, use_container_width=True) st.dataframe(violations, hide_index=True, use_container_width=True)
``` ```
- [ ] **Step 2: Commit** - [x] **Step 2: Commit**
```bash ```bash
git add dashboard/src/agentforge_dashboard/pages/4_📜_Historial.py git add dashboard/src/agentforge_dashboard/pages/4_📜_Historial.py
@@ -5501,7 +5507,7 @@ git commit -m "feat(dashboard): página Historial con tabs ejecuciones y violaci
**Files:** **Files:**
- Create: `dashboard/src/agentforge_dashboard/pages/5_📐_Politicas.py` - Create: `dashboard/src/agentforge_dashboard/pages/5_📐_Politicas.py`
- [ ] **Step 1: Implementar** - [x] **Step 1: Implementar**
```python ```python
"""Página de políticas de guardrails y sus versiones.""" """Página de políticas de guardrails y sus versiones."""
@@ -5552,7 +5558,7 @@ versions = client.list_policy_versions(selected)
st.dataframe(versions, hide_index=True, use_container_width=True) st.dataframe(versions, hide_index=True, use_container_width=True)
``` ```
- [ ] **Step 2: Commit** - [x] **Step 2: Commit**
```bash ```bash
git add dashboard/src/agentforge_dashboard/pages/5_📐_Politicas.py git add dashboard/src/agentforge_dashboard/pages/5_📐_Politicas.py
@@ -5563,6 +5569,10 @@ git commit -m "feat(dashboard): página Politicas con detalle de validadores y v
## Phase I — Dockerización (Tasks 3637) ## Phase I — Dockerización (Tasks 3637)
> **Nota de implementación (desviación del plan):**
> - **Task 36:** ambos Dockerfiles pasan `docker build --check` sin warnings (se usó como lint previo).
> - **Task 37 (smoke):** `docker compose build` falló la primera vez en `RUN python -m spacy download en_core_web_sm` del core — `guardrails-ai<0.6` arrastra `typer 0.12.x`, incompatible con el `click 8.3.x` que resolvió pip (`TypeError: Secondary flag is not valid for non-boolean flag`). Se mantuvo el `spacy download` del plan y se fijó `click>=8.1,<8.2` en `core/requirements.txt` (commit `fix(deps): fija click<8.2 …`); el rebuild funcionó. Smoke OK: `docker compose up -d` → `agentforge-core` *healthy* con `GET /health → 200 {"status":"ok"}`, `agentforge-dashboard` con `/_stcore/health → ok`, sin errores en logs; `docker compose down` limpio.
### Task 36: Dockerfiles para core y dashboard ### Task 36: Dockerfiles para core y dashboard
**Files:** **Files:**
@@ -5570,7 +5580,7 @@ git commit -m "feat(dashboard): página Politicas con detalle de validadores y v
- Create: `dashboard/Dockerfile` - Create: `dashboard/Dockerfile`
- Create: `.dockerignore` - Create: `.dockerignore`
- [ ] **Step 1: `core/Dockerfile`** - [x] **Step 1: `core/Dockerfile`**
```dockerfile ```dockerfile
# syntax=docker/dockerfile:1.7 # syntax=docker/dockerfile:1.7
@@ -5611,7 +5621,7 @@ HEALTHCHECK --interval=10s --timeout=3s --start-period=15s --retries=3 \
CMD ["uvicorn", "agentforge_core.main:app", "--host", "0.0.0.0", "--port", "8000"] CMD ["uvicorn", "agentforge_core.main:app", "--host", "0.0.0.0", "--port", "8000"]
``` ```
- [ ] **Step 2: `dashboard/Dockerfile`** - [x] **Step 2: `dashboard/Dockerfile`**
```dockerfile ```dockerfile
# syntax=docker/dockerfile:1.7 # syntax=docker/dockerfile:1.7
@@ -5647,7 +5657,7 @@ CMD ["streamlit", "run", "/app/src/agentforge_dashboard/app.py", \
"--server.headless=true", "--browser.gatherUsageStats=false"] "--server.headless=true", "--browser.gatherUsageStats=false"]
``` ```
- [ ] **Step 3: `.dockerignore`** - [x] **Step 3: `.dockerignore`**
``` ```
.git .git
@@ -5666,7 +5676,7 @@ docs/superpowers/plans
tests tests
``` ```
- [ ] **Step 4: Commit** - [x] **Step 4: Commit**
```bash ```bash
git add core/Dockerfile dashboard/Dockerfile .dockerignore git add core/Dockerfile dashboard/Dockerfile .dockerignore
@@ -5680,7 +5690,7 @@ git commit -m "build: añade Dockerfiles para core y dashboard con healthchecks
**Files:** **Files:**
- Create: `docker-compose.yml` - Create: `docker-compose.yml`
- [ ] **Step 1: `docker-compose.yml`** - [x] **Step 1: `docker-compose.yml`**
```yaml ```yaml
services: services:
@@ -5728,7 +5738,7 @@ services:
restart: unless-stopped restart: unless-stopped
``` ```
- [ ] **Step 2: Verificar build + smoke** - [x] **Step 2: Verificar build + smoke**
```bash ```bash
docker compose build docker compose build
@@ -5742,7 +5752,7 @@ docker compose down
Si los dos healthchecks devuelven 200 y los logs no tienen errores, el smoke pasa. Si los dos healthchecks devuelven 200 y los logs no tienen errores, el smoke pasa.
- [ ] **Step 3: Commit** - [x] **Step 3: Commit**
```bash ```bash
git add docker-compose.yml git add docker-compose.yml
@@ -5761,7 +5771,7 @@ git commit -m "build: añade docker-compose con dos servicios y healthchecks"
- Create: `docs/futuro.md` - Create: `docs/futuro.md`
- Create: `docs/manual_qa.md` - Create: `docs/manual_qa.md`
- [ ] **Step 1: `README.md`** - [x] **Step 1: `README.md`**
```markdown ```markdown
# 🛡️ AgentForge # 🛡️ AgentForge
@@ -5867,7 +5877,7 @@ make smoke # docker-compose + curl health
MIT (a confirmar). MIT (a confirmar).
``` ```
- [ ] **Step 2: `ARCHITECTURE.md`** - [x] **Step 2: `ARCHITECTURE.md`**
```markdown ```markdown
# AgentForge — Arquitectura técnica # AgentForge — Arquitectura técnica
@@ -5943,7 +5953,7 @@ nodo `approve_gate`. Sólo pausa cuando hay acciones de alto riesgo
Ver [`docs/futuro.md`](docs/futuro.md). Ver [`docs/futuro.md`](docs/futuro.md).
``` ```
- [ ] **Step 3: `docs/futuro.md`** - [x] **Step 3: `docs/futuro.md`**
```markdown ```markdown
# Roadmap (post-MVP) # Roadmap (post-MVP)
@@ -5963,7 +5973,7 @@ Ver [`docs/futuro.md`](docs/futuro.md).
- **Promoción explícita draft → active** vía PR/aprobación. - **Promoción explícita draft → active** vía PR/aprobación.
``` ```
- [ ] **Step 4: `docs/manual_qa.md`** - [x] **Step 4: `docs/manual_qa.md`**
```markdown ```markdown
# Smoke manual del dashboard # Smoke manual del dashboard
@@ -6026,7 +6036,7 @@ Abrir [http://localhost:8501](http://localhost:8501).
pendientes. pendientes.
``` ```
- [ ] **Step 5: Commit final** - [x] **Step 5: Commit final**
```bash ```bash
git add README.md ARCHITECTURE.md docs/futuro.md docs/manual_qa.md git add README.md ARCHITECTURE.md docs/futuro.md docs/manual_qa.md