Skip to content

Commit 31b77f1

Browse files
authored
Merge pull request #167 from 2-Coatl/feature/implement-hamilton-framework-with-sdlc-11-28-51
Refactor Hamilton workspace tests into infrastructure tree
2 parents 93dd70f + f701255 commit 31b77f1

10 files changed

Lines changed: 182 additions & 13 deletions

File tree

docs/EXECPLAN_hamilton_llm_dataflow_example.md

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@ Queremos que cualquier integrante del proyecto pueda ejecutar un ejemplo mínimo
99
## Progress
1010

1111
- [x] (2025-11-19 10:00Z) ExecPlan creado y alcance documentado.
12-
- [x] (2025-11-19 10:25Z) Pruebas unitarias que describen el dataflow Hamilton deseado creadas en scripts/coding/tests/ai/examples/test_hamilton_llm_example.py.
12+
- [x] (2025-11-19 10:25Z) Pruebas unitarias que describen el dataflow Hamilton deseado creadas en `scripts/coding/tests/ai/examples/test_hamilton_llm_example.py` (ahora residiendo en `infrastructure/workspace/tests/hamilton_llm/test_driver.py`).
13+
- [x] (2025-11-19 12:20Z) Registro de suites de prueba en `infrastructure.workspace.TEST_SUITES` y reubicación del paquete de pruebas a `infrastructure/workspace/tests/hamilton_llm/`.
1314
- [x] (2025-11-19 11:05Z) Implementación del ejemplo Hamilton (driver, dataflow y cliente LLM) con pruebas pasando.
1415
- [x] (2025-11-19 11:20Z) Documentación actualizada (guía Hamilton e índice general) y validaciones ejecutadas.
1516
- [x] (2025-11-13 11:05Z) Refactor del driver para exponer Builder/Driver/DictResult estilo apache/hamilton y ampliación de pruebas.
@@ -33,6 +34,9 @@ Queremos que cualquier integrante del proyecto pueda ejecutar un ejemplo mínimo
3334
- Decision: Trasladar el ejemplo Hamilton al árbol `infrastructure/workspace` para alinearlo con la organización de entornos ejecutables y facilitar su descubrimiento desde infraestructura.
3435
Rationale: El ejemplo sirve como workspace autocontenible; ubicarlo junto al resto de utilidades de infraestructura responde a la retroalimentación del stakeholder y mantiene la separación documentación/código.
3536
Date/Author: 2025-11-19 / coding-agent
37+
- Decision: Registrar las suites de prueba del workspace en `infrastructure.workspace.TEST_SUITES` para que automatizaciones y documentación puedan descubrirlas sin depender de rutas históricas.
38+
Rationale: La reubicación desde `scripts/coding/tests/` rompía la convención previa; proveer un registro explícito evita referencias obsoletas en guías y herramientas.
39+
Date/Author: 2025-11-19 / coding-agent
3640

3741
## Outcomes & Retrospective
3842

@@ -42,7 +46,7 @@ Las pruebas de documentación existentes siguen fallando por deuda histórica; s
4246

4347
## Context and Orientation
4448

45-
El repositorio organiza scripts de agentes en `scripts/coding/ai/` y pruebas correspondientes en `scripts/coding/tests/`. La guía `docs/gobernanza/ai/HAMILTON_FRAMEWORK_INTEGRACION_SDLC.md` solicita como siguiente paso incorporar ejemplos de código Hamilton usando TDD. Actualmente no existe un paquete que demuestre un dataflow Hamilton; tampoco tenemos dependencias a `sf-hamilton`. Implementaremos un micro-driver declarativo interno inspirado en Hamilton, suficiente para ejecutar funciones nombradas según los nodos del grafo y resolver dependencias mediante introspección. Las pruebas se ubicarán en `scripts/coding/tests/ai/examples/` para mantener la correspondencia.
49+
El repositorio organiza scripts de agentes en `scripts/coding/ai/` y pruebas correspondientes en `scripts/coding/tests/`. La guía `docs/gobernanza/ai/HAMILTON_FRAMEWORK_INTEGRACION_SDLC.md` solicita como siguiente paso incorporar ejemplos de código Hamilton usando TDD. Actualmente no existe un paquete que demuestre un dataflow Hamilton; tampoco tenemos dependencias a `sf-hamilton`. Implementaremos un micro-driver declarativo interno inspirado en Hamilton, suficiente para ejecutar funciones nombradas según los nodos del grafo y resolver dependencias mediante introspección. Las pruebas residirán en `infrastructure/workspace/tests/hamilton_llm/` para mantenerlas junto al workspace correspondiente.
4650

4751
El ejemplo debe incluir:
4852
1. Una representación explícita de la diferencia entre flujos de desarrollo ML tradicional y LLM, ya sea en docstrings o constantes que puedan inspeccionarse desde las pruebas.
@@ -54,7 +58,7 @@ El ejemplo debe incluir:
5458

5559
1. Crear paquete `infrastructure/workspace/hamilton_llm/` con archivos `__init__.py`, `dataflow.py` y `llm_client.py`. `dataflow.py` contendrá funciones declarativas (topic, prompt_template, prompt, llm_response, business_value, cost_estimate). `llm_client.py` expondrá una clase `MockLLMClient` parametrizable. Documentar en docstrings las diferencias de ritmo de desarrollo.
5660
2. Implementar micro driver en `infrastructure/workspace/hamilton_llm/driver.py` que resuelva dependencias mediante inspección de firmas, exponiendo además un `Builder` y adaptadores `DictResult` compatibles con la API oficial. La ejecución debe aceptar configuración base (`with_config`) y adaptadores encadenables.
57-
3. Escribir pruebas TDD en `scripts/coding/tests/ai/examples/test_hamilton_llm_example.py` que:
61+
3. Escribir pruebas TDD en `infrastructure/workspace/tests/hamilton_llm/test_driver.py` que:
5862
- Construyan el driver con el módulo `dataflow`.
5963
- Injecten entradas (por ejemplo, `idea`, `domain_data`, `pricing_policy`).
6064
- Verifiquen que `llm_response` y `business_value` devuelvan valores esperados.
@@ -63,12 +67,12 @@ El ejemplo debe incluir:
6367
5. Implementar código real en los módulos descritos, asegurando cobertura >80 % mediante pruebas que ejerciten rutas principales, errores controlados (por ejemplo, dependencia faltante) y adaptadores personalizados.
6468
6. Re-ejecutar pytest (Green) y refactorizar si procede.
6569
7. Actualizar `docs/gobernanza/ai/HAMILTON_FRAMEWORK_INTEGRACION_SDLC.md` en la sección de próximos pasos para referenciar el nuevo ejemplo y añadir entrada en `docs/index.md` si corresponde.
66-
8. Documentar en el ExecPlan las decisiones, sorpresas y resultados. Incluir instrucciones de validación (`python3 -m pytest scripts/coding/tests/ai/examples/test_hamilton_llm_example.py`).
70+
8. Documentar en el ExecPlan las decisiones, sorpresas y resultados. Incluir instrucciones de validación (`python3 -m pytest infrastructure/workspace/tests/hamilton_llm/test_driver.py`).
6771
9. Mantener el shim alineado con apache/hamilton agregando pruebas de Builder y adaptadores para evitar regresiones.
6872

6973
## Concrete Steps
7074

71-
1. Añadir pruebas fallidas: crear archivo de test y ejecutar `python3 -m pytest scripts/coding/tests/ai/examples/test_hamilton_llm_example.py` desde la raíz del repo.
75+
1. Añadir pruebas fallidas: crear archivo de test y ejecutar `python3 -m pytest infrastructure/workspace/tests/hamilton_llm/test_driver.py` desde la raíz del repo.
7276
2. Implementar paquetes y funciones según el plan, escribir docstrings que recojan la narrativa de ritmo de desarrollo y habilidades SWE.
7377
3. Añadir pruebas de Builder/adaptadores (`test_custom_adapter_transforms_execution_result`, `test_builder_requires_modules_before_building`) antes de implementar el shim.
7478
4. Ejecutar pytest nuevamente hasta que pase y revisar cobertura si se añade reporte.
@@ -77,7 +81,7 @@ El ejemplo debe incluir:
7781

7882
## Validation and Acceptance
7983

80-
- `python3 -m pytest scripts/coding/tests/ai/examples/test_hamilton_llm_example.py` debe pasar, mostrando que el driver ejecuta correctamente el dataflow y que la metadata esperada está disponible.
84+
- `python3 -m pytest infrastructure/workspace/tests/hamilton_llm/test_driver.py` debe pasar, mostrando que el driver ejecuta correctamente el dataflow y que la metadata esperada está disponible.
8185
- `python3 -m pytest docs/qa/testing/test_documentation_alignment.py` debe continuar pasando, confirmando integridad documental.
8286
- La documentación Hamilton debe mencionar explícitamente el nuevo ejemplo.
8387

@@ -89,9 +93,9 @@ El driver declarativo resolverá dependencias determinísticamente, por lo que e
8993

9094
Salida relevante de validaciones más recientes:
9195

92-
- `python3 -m pytest scripts/coding/tests/ai/examples/test_hamilton_llm_example.py`
96+
- `python3 -m pytest infrastructure/workspace/tests/hamilton_llm/test_driver.py`
9397

94-
scripts/coding/tests/ai/examples/test_hamilton_llm_example.py .....
98+
infrastructure/workspace/tests/hamilton_llm/test_driver.py .....
9599

96100
- `python3 -m pytest docs/qa/testing/test_documentation_alignment.py` (sigue fallando por deuda documental heredada)
97101

docs/gobernanza/ai/HAMILTON_FRAMEWORK_INTEGRACION_SDLC.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ Cada subsección resume objetivos, acciones Hamilton y validaciones alineadas co
132132

133133
## 6. Próximos pasos
134134

135-
1. Ejemplo base publicado en `infrastructure/workspace/hamilton_llm/`: driver declarativo + pruebas `scripts/coding/tests/ai/examples/test_hamilton_llm_example.py`. A partir de este flujo se pueden derivar variantes (e.g. adaptadores FastAPI) conservando el enfoque TDD.
135+
1. Ejemplo base publicado en `infrastructure/workspace/hamilton_llm/`: driver declarativo + pruebas `infrastructure/workspace/tests/hamilton_llm/test_driver.py`. A partir de este flujo se pueden derivar variantes (e.g. adaptadores FastAPI) conservando el enfoque TDD.
136136
2. Evaluar integración con `TASK-024-ai-telemetry-system.md` para recolectar métricas de ejecución.
137137
3. Registrar aprendizajes en `docs/qa/registros/` una vez ejecutados pilotos.
138138

docs/index.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ Este índice combina lo implementado con la visión futura del proyecto, clarame
8787
- **Métricas DORA**: [`scripts/dora_metrics.py`](../scripts/dora_metrics.py)
8888
- **Templates**: [`scripts/templates/`](../scripts/templates/)
8989
- **Gestión de contexto multi-LLM**: [`ai_capabilities/orchestration/CONTEXT_MANAGEMENT_PLAYBOOK.md`](ai_capabilities/orchestration/CONTEXT_MANAGEMENT_PLAYBOOK.md) y módulo reutilizable [`scripts/coding/ai/shared/context_sessions.py`](../scripts/coding/ai/shared/context_sessions.py).
90-
- **Hamilton Data→Prompt→LLM ejemplo**: [`infrastructure/workspace/hamilton_llm/`](../infrastructure/workspace/hamilton_llm/) con pruebas [`scripts/coding/tests/ai/examples/test_hamilton_llm_example.py`](../scripts/coding/tests/ai/examples/test_hamilton_llm_example.py).
90+
- **Hamilton Data→Prompt→LLM ejemplo**: [`infrastructure/workspace/hamilton_llm/`](../infrastructure/workspace/hamilton_llm/) con pruebas [`infrastructure/workspace/tests/hamilton_llm/test_driver.py`](../infrastructure/workspace/tests/hamilton_llm/test_driver.py).
9191

9292
#### [PLANIFICADO] Planificados (ver [`docs/scripts/README.md`](scripts/README.md))
9393
- `scripts/sdlc_agent.py` - CLI SDLC

docs/infraestructura/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,4 +23,4 @@ Cada carpeta ofrece un README inicial listo para documentar los artefactos corre
2323
## Recursos destacados recientes
2424
- **CPython precompilado**: consulta el [pipeline y guía de DevContainer](cpython_precompilado/pipeline_devcontainer.md) para entender cómo se construye, publica y consume el intérprete optimizado.【F:docs/infrastructure/cpython_precompilado/pipeline_devcontainer.md†L1-L99】
2525
- **Scripts oficiales**: `build_cpython.sh`, `validate_build.sh` e `install_prebuilt_cpython.sh` viven en `infrastructure/cpython/scripts/` y cuentan con pruebas en `infrastructure/cpython/tests/`.
26-
- **Workspace Hamilton LLM**: la carpeta [`workspace`](workspace/README.md) concentra el ejemplo `Data → Prompt → LLM → $` situado en `infrastructure/workspace/hamilton_llm/`, con pruebas asociadas en `scripts/coding/tests/ai/examples/test_hamilton_llm_example.py`.
26+
- **Workspace Hamilton LLM**: la carpeta [`workspace`](workspace/README.md) concentra el ejemplo `Data → Prompt → LLM → $` situado en `infrastructure/workspace/hamilton_llm/`, con pruebas asociadas en `infrastructure/workspace/tests/hamilton_llm/test_driver.py`.

docs/infraestructura/workspace/README.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ Este workspace agrupa los artefactos ejecutables que acompañan la guía de inte
55
## Ubicación del código
66

77
- **Paquete principal**: `infrastructure/workspace/hamilton_llm/`
8-
- **Pruebas asociadas**: `scripts/coding/tests/ai/examples/test_hamilton_llm_example.py`
8+
- **Pruebas asociadas**: `infrastructure/workspace/tests/hamilton_llm/test_driver.py`
99

1010
El paquete contiene el driver declarativo (`driver.py`), el dataflow (`dataflow.py`) y el cliente LLM determinista (`llm_client.py`).
1111

@@ -17,7 +17,9 @@ El paquete contiene el driver declarativo (`driver.py`), el dataflow (`dataflow.
1717
## Cómo ejecutarlo
1818

1919
```bash
20-
python3 -m pytest scripts/coding/tests/ai/examples/test_hamilton_llm_example.py
20+
python3 -m pytest infrastructure/workspace/tests/hamilton_llm/test_driver.py
2121
```
2222

2323
La prueba valida tanto el linaje del dataflow como el manejo de dependencias ausentes, permitiendo extender el workspace mediante TDD.
24+
25+
Para verificar la alineación estructural del workspace, se expone además `infrastructure/workspace/tests/test_registry.py`, que afirma la presencia de `TEST_SUITES` en el paquete raíz y que el workspace Hamilton queda registrado para futuras automatizaciones.
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,12 @@
11
"""Workspace automation modules, including Hamilton examples."""
2+
3+
from pathlib import Path
4+
5+
from . import hamilton_llm
6+
7+
__all__ = ("hamilton_llm",)
8+
9+
TEST_SUITES = {
10+
"hamilton_llm": Path("infrastructure/workspace/tests/hamilton_llm"),
11+
}
12+
"""Mapping from workspace identifier to the directory containing its tests."""

infrastructure/workspace/tests/__init__.py

Whitespace-only changes.

infrastructure/workspace/tests/hamilton_llm/__init__.py

Whitespace-only changes.
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
"""Tests for the Hamilton-style LLM dataflow example located in the workspace tree."""
2+
3+
import pytest
4+
5+
from infrastructure.workspace.hamilton_llm import dataflow
6+
from infrastructure.workspace.hamilton_llm import driver as mini_driver
7+
from infrastructure.workspace.hamilton_llm.driver import MissingDependencyError
8+
from infrastructure.workspace.hamilton_llm.llm_client import MockLLMClient
9+
10+
11+
@pytest.fixture()
12+
def hamilton_driver():
13+
return (
14+
mini_driver.Builder()
15+
.with_modules(dataflow)
16+
.with_config({"pricing_policy": {"price_per_1k_tokens": 0.4, "safety_multiplier": 1.15}})
17+
.with_adapters(mini_driver.DictResult())
18+
.build()
19+
)
20+
21+
22+
def test_pace_of_development_metadata_matches_expected_sequence():
23+
"""Validate that the module exposes the canonical pacing differences described in the slides."""
24+
assert dataflow.PACE_OF_DEVELOPMENT["traditional_ml"] == [
25+
"Idea & Data/Resources",
26+
"Design",
27+
"Development/Prototype",
28+
"Model Development",
29+
"Getting to Production",
30+
"Operations",
31+
"Maintenance & Business Value",
32+
]
33+
assert dataflow.PACE_OF_DEVELOPMENT["llm_apps"] == [
34+
"Idea & Data/Resources",
35+
"Design",
36+
"Development/Prototype",
37+
"Prompt / Model Development",
38+
"Getting to Production",
39+
"Operations",
40+
"Maintenance & Business Value",
41+
]
42+
43+
44+
def test_hamilton_builder_executes_llm_business_flow(hamilton_driver):
45+
"""End-to-end execution should transform data into a business value package and cost estimate."""
46+
mock_client = MockLLMClient(
47+
price_per_1k_tokens=0.4,
48+
response_catalog={
49+
"Data → Prompt → LLM → $": "Use Hamilton declarative functions to keep prompts versioned and guarded against injection.",
50+
},
51+
)
52+
53+
inputs = {
54+
"idea": "AI copilots for compliance analysts",
55+
"domain_data": {
56+
"data": "archived compliance tickets",
57+
"ui": "browser extension",
58+
"business_process": "regulatory audit",
59+
},
60+
"edge_cases": [
61+
"Input state space",
62+
"Guard against prompt injection",
63+
"Domain expertise",
64+
"Evaluation",
65+
"Cost/GPUs",
66+
],
67+
"llm_client": mock_client,
68+
}
69+
70+
result = hamilton_driver.execute(["business_value", "cost_estimate"], inputs)
71+
72+
assert result["business_value"]["llm_plan"].startswith("Use Hamilton declarative functions")
73+
assert result["business_value"]["next_step"] == "Prototype with guarded prompts"
74+
assert pytest.approx(result["cost_estimate"], rel=1e-3) == 0.0552
75+
76+
executed = hamilton_driver.execution_log
77+
assert executed[-1] == "cost_estimate"
78+
assert "llm_response" in executed
79+
assert executed.index("business_value") < executed.index("cost_estimate")
80+
81+
82+
def test_driver_reports_missing_inputs():
83+
driver = mini_driver.Builder().with_modules(dataflow).build()
84+
mock_client = MockLLMClient(price_per_1k_tokens=0.5, response_catalog={})
85+
86+
with pytest.raises(MissingDependencyError) as exc:
87+
driver.execute(
88+
["cost_estimate"],
89+
{
90+
"idea": "Guardrails demo",
91+
"domain_data": {"data": "logs", "ui": "cli", "business_process": "ops"},
92+
"edge_cases": ["Injection"],
93+
"llm_client": mock_client,
94+
},
95+
)
96+
97+
assert "pricing_policy" in str(exc.value)
98+
99+
100+
def test_builder_requires_modules_before_building():
101+
with pytest.raises(ValueError) as exc:
102+
mini_driver.Builder().build()
103+
104+
assert "modules" in str(exc.value).lower()
105+
106+
107+
def test_custom_adapter_transforms_execution_result():
108+
class KeysAdapter:
109+
def __call__(self, results):
110+
return tuple(sorted(results))
111+
112+
driver = (
113+
mini_driver.Builder()
114+
.with_modules(dataflow)
115+
.with_adapters(KeysAdapter())
116+
.build()
117+
)
118+
119+
assert driver.execute(["pace_of_development"], {}) == ("pace_of_development",)
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
"""Structural tests ensuring workspace modules expose their test locations."""
2+
3+
from importlib import import_module
4+
from pathlib import Path
5+
6+
import pytest
7+
8+
9+
@pytest.fixture(scope="module")
10+
def workspace_pkg():
11+
return import_module("infrastructure.workspace")
12+
13+
14+
def test_workspace_exposes_hamilton_llm_suite(workspace_pkg):
15+
"""The workspace package should document the canonical location of its tests."""
16+
suites = getattr(workspace_pkg, "TEST_SUITES")
17+
assert "hamilton_llm" in suites
18+
19+
suite_path = Path(suites["hamilton_llm"])
20+
assert suite_path.parts[:3] == ("infrastructure", "workspace", "tests")
21+
assert suite_path.name == "hamilton_llm"
22+
23+
24+
def test_suite_path_points_to_existing_directory(workspace_pkg):
25+
suites = workspace_pkg.TEST_SUITES
26+
suite_path = Path(suites["hamilton_llm"])
27+
assert suite_path.exists(), "El workspace debe registrar un directorio real de pruebas"
28+
29+
30+
def test_workspace_exports_documented_modules(workspace_pkg):
31+
"""Ensure __all__ helps discovery tools locate available workspaces."""
32+
exported = set(getattr(workspace_pkg, "__all__", ()))
33+
assert "hamilton_llm" in exported, "El workspace Hamilton debe exponerse en __all__"

0 commit comments

Comments
 (0)