chore: snapshot WIP previo + flow 0008 + 7 sub-issues (0112-0119)

Snapshot de WIP acumulado de sesiones previas antes de merge wave 1
del flow 0008 (kanban_cpp + agent_runner_api + DoD schema).

Incluye:
- dev/flows/0008-kanban-cpp-and-agent-workflows.md
- dev/issues/0112-0119*.md (7 sub-issues)
- WIP previo en cmd/fn/doctor.go, registry/*, modules/, cpp/, etc.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-18 18:17:08 +02:00
parent ddb5366884
commit b9716a7cd6
119 changed files with 14929 additions and 3084 deletions
+134
View File
@@ -0,0 +1,134 @@
---
id: "0110"
title: "Gap registry: helper HTTP cliente C++ (curl/popen) reutilizable"
status: pendiente
type: feature
domain:
- cpp-stack
- registry-quality
scope: registry
priority: media
depends: []
blocks:
- "0111"
related:
- "0106"
created: 2026-05-18
updated: 2026-05-18
tags: [http, cpp, registry-gap, curl, helper]
---
# 0110 — Helper HTTP cliente C++ en el registry
## Problema
Hoy no existe funcion HTTP cliente reutilizable en `cpp/functions/`. Cada app C++ que necesita
golpear un endpoint reinventa la capa:
| App | Fichero | Tecnica | LOC aprox |
|---|---|---|---|
| `apps/services_monitor/` | `http_client.cpp` | cURL popen/WinHTTP segun plataforma | ~150 |
| `apps/dag_engine_ui/` | inline en `main.cpp` | curl CLI via popen + parse | ~80 |
| `apps/data_factory/` | inline | popen curl | ~60 |
| `cpp/functions/core/llm_anthropic.cpp` | propio | cURL popen — solo Anthropic | — |
| `apps/process_explorer/` (issue 0111) | `http_client.cpp` local | pendiente — clonara services_monitor | ~150 esperados |
El patron ya supera el umbral `>2x` que dispara la regla de promocion (CLAUDE.md
"Si patron se repite >2x → propose nueva funcion via fn-constructor"). Cada app duplica:
- Detection de plataforma (Linux: `popen("curl -s ...")`, Win: `WinHTTPOpen`/popen)
- Manejo de basicAuth / Bearer tokens
- Timeouts
- Captura de body + status code
- Manejo de errores transitorios (DNS, conexion rechazada)
## Decision
Anadir al registry dos funciones C++ en dominio `core` (o `infra`):
### `http_request_cpp_core` (impure)
```cpp
namespace fn_http {
struct Request {
std::string method; // "GET", "POST", "PUT", "DELETE"
std::string url;
std::vector<std::pair<std::string,std::string>> headers;
std::string body; // raw bytes (JSON, etc.)
int timeout_ms = 5000;
std::string bearer_token; // shortcut: anade Authorization: Bearer <token>
std::string basic_user; // shortcut: anade Authorization: Basic base64(user:pass)
std::string basic_pass;
};
struct Response {
int status = 0; // 0 = error de transporte
std::string body;
std::vector<std::pair<std::string,std::string>> headers;
std::string error; // vacio si OK
int64_t duration_ms = 0;
};
Response request(const Request& req);
}
```
Implementacion: cURL via popen (portable WSL+Win+Linux, igual que `llm_anthropic`).
Si en el futuro queremos rendimiento real, swap a libcurl linkado estaticamente
o WinHTTP via `#ifdef _WIN32` — interfaz Request/Response no cambia.
### `http_get_json_cpp_core` (impure, pure wrapper)
Helper que envuelve `http_request` + parse JSON (via `nlohmann::json` o similar
ya disponible en el repo) para los casos comunes:
```cpp
namespace fn_http {
// Devuelve parsed JSON o lanza si status != 2xx
nlohmann::json get_json(const std::string& url,
const std::string& bearer_token = "",
int timeout_ms = 5000);
}
```
## Plan de migracion
Tras crear las funciones, abrir issue separado por cada consumer para migrar:
1. `apps/services_monitor/http_client.cpp` -> usar `fn_http::request`
2. `apps/dag_engine_ui/main.cpp` (inline)
3. `apps/data_factory/` (inline)
4. `cpp/functions/core/llm_anthropic.cpp` — refactor para usar `fn_http::request` por
debajo (mantiene API publica)
5. `apps/process_explorer/` (issue 0111) — nace ya usando el helper
## Criterios de aceptacion
- [ ] `cpp/functions/core/http_request.{cpp,h,md}` registrado en `registry.db`
- [ ] `cpp/functions/core/http_get_json.{cpp,h,md}` idem
- [ ] Tests visuales o de integracion contra `httpbin.org` (200/404/timeout/auth)
- [ ] Frontmatter completo (`params`/`output`/`tags`/`example`)
- [ ] `.md` cumple contrato self-doc (`## Ejemplo`, `## Cuando usarla`, `## Gotchas`)
- [ ] Al menos 1 consumer migrado para validar API (recomendado `services_monitor`)
- [ ] `fn doctor uses-functions` limpio
## Gotchas conocidos
- cURL popen en Windows necesita `curl.exe` en PATH — todos los WSL/Win lo tienen,
pero documentar en `## Gotchas`.
- Bodies binarios: popen complica el escape; primera version solo string bodies.
- TLS verify: por defecto on; permitir `req.insecure = true` solo para testing.
- Timeouts: cURL `--max-time` cubre handshake+transfer; documentar diferencia con
read-timeout puro.
## Por que no usar libcurl linkado
- `popen("curl ...")` no requiere anadir libcurl al toolchain MinGW cross-compile
(que ya costo configurar). `llm_anthropic` lleva meses funcionando asi.
- Cuando aparezca un caso real de latencia (>10 req/s sostenido), abrimos issue
separado para swap a libcurl.
## Out of scope (no en este issue)
- WebSocket / SSE — cliente WS C++ es otro gap; abrir issue propio cuando aplique.
- Cliente gRPC.
- Streaming responses (SSE chunk-by-chunk) — usar caso de `dag_engine_ui` para
decidir cuando.