Commit Graph

120 Commits

Author SHA1 Message Date
egutierrez 4302212b34 feat(ml): implementa camino sv3d en comfyui_generate_views_from_image
Completa la rama method='sv3d' (antes NotImplementedError) componiendo el
workflow SV3D nativo de ComfyUI (SV3D_Conditioning + VideoLinearCFGGuidance +
KSampler + VAEDecode + SaveImage): una imagen produce un orbit de N frames
equiespaciados en 360 grados en una pasada.

- _METHOD_CKPT['sv3d'] acepta sv3d_p (preferido) o sv3d_u; nuevo helper
  _resolve_ckpt sustituye a _method_ckpt_key.
- nuevos params keyword-only video_frames=21, sv3d_width=576, sv3d_height=576
  (configurables para densidad de orbit y control de VRAM).
- salida sv3d extendida con frames (orbit completo) + frame_count; views mapea
  cada azimuth al frame del orbit mas cercano (cardinales para multi-vista).
- _collect_views_sv3d + helpers compartidos _history_images/_fetch_or_name;
  _collect_views (zero123) refactorizado para reusarlos.

Probado en GPU (8 GB lowvram): sv3d_p.safetensors descargado a checkpoints/,
21 frames 576x576 en ~75 s, peak ~5.7 GB, sin OOM
(prompt_id 0caeedf4-baa0-4c8f-844a-867490ac4f85). Detalle en report 0128.

Bumpa version 1.0.0 -> 1.1.0 + Capability growth log. Pagina madre comfyui.md
marca ambos caminos (zero123/sv3d) operativos.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-24 19:57:10 +02:00
egutierrez 394221f8c7 feat(ml): pipeline replicar imagen desde link de Civitai
Nueva capacidad del grupo comfyui: dado el id/URL de una imagen de Civitai,
extrae cómo se generó (prompt, modelo, sampler, LoRAs) vía los endpoints tRPC
image.getGenerationData + image.get (la API v1 da meta=null), reconstruye el
workflow y lo replica en nuestro ComfyUI, sustituyendo el checkpoint ausente por
el más parecido instalado y reportando lo que falta en missing_models sin bajar
nada a ciegas. Respeta SFW.

Funciones nuevas (registry-first, componen 8 funciones existentes):
- comfyui_fetch_civitai_image_meta_py_ml (impura): observa la receta por id/URL.
- comfyui_map_a1111_params_py_ml (pura): traduce meta A1111 -> params ComfyUI,
  familia del modelo y LoRAs.
- comfyui_replicate_civitai_oneshot_py_pipelines: orquesta fetch_meta ->
  map_a1111_params -> build/embebido -> run_foreign_workflow_oneshot -> judge.

Probado en vivo (imagen SFW 23526611): receta extraída + réplica 1024x1024
generada + panel de jueces. 12 tests unitarios verdes. Capability page comfyui.md
actualizada. Report 0127.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-24 19:25:31 +02:00
egutierrez 69d9aed46a feat(ml): mixer de capacidades comfyui (compose + generate_mixed_oneshot + inject controlnet/ipadapter)
Mezclador del grupo comfyui-skill que promueve a una sola llamada la secuencia
base -> compose -> submit -> wait -> fetch -> judge (issue 0087):

- comfyui_compose_capabilities_py_ml (PURA): aplica en orden las capacidades
  activadas (loras, controlnet, ipadapter, facedetailer, hires) sobre un
  workflow base, sin mutar la entrada.
- comfyui_generate_mixed_oneshot_py_pipelines: one-shot que resuelve el base
  (skill/txt2img/dict), compone, encola, espera, descarga el PNG y lo puntua
  con el panel comfyui-judge.
- comfyui_inject_controlnet_py_ml, comfyui_inject_ipadapter_py_ml: inyectores
  encadenables que consume el compose.
- Tests (24 passed) + pagina madre docs/capabilities/comfyui-skill.md.

Prueba real en GPU: txt2img dreamshaper_8 + 2 LoRAs (3d_render_redmond +
detail_tweaker) + FaceDetailer -> imagen 512x512 en ~24s, juez verdict 'good'
(score 4.69, votos aesthetic+clip good; voto llm degradado por rate-limit 429).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-24 19:02:10 +02:00
egutierrez 3887e59092 feat(ml): auto-commit con 6 cambios
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-24 17:47:28 +02:00
egutierrez 5f0df32728 fix(browser): limpiar previews/outputs residuales al cargar workflow ComfyUI
app.loadApiJson (lo que usa comfyui_load_workflow_ui) reconstruye el grafo pero
no llama a app.clean(), por lo que no resetea el store app.nodeOutputs ni los
previews de los nodos. Cuando un workflow nuevo reusa un node_id existente en el
store, el preview cacheado del workflow anterior se re-pinta sobre el nodo nuevo
(visto: imagen 3D pegada bajo un CheckpointLoaderSimple/SaveGLB).

- Nueva funcion comfyui_clear_node_outputs_ui: limpieza no destructiva del store
  app.nodeOutputs + node.imgs/images, sin tocar la topologia del grafo.
- comfyui_load_workflow_ui v1.1.0: anade clear_outputs=True (default) que invoca
  la limpieza antes de loadApiJson, replicando la garantia de loadGraphData.

Reproducido y verificado en la UI real (CDP 9222) con evidencia antes/despues.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-24 17:37:07 +02:00
egutierrez 04ecf9f394 feat(ml): comfyui_export_skill_template — skills (recetas) como grafos cargables en el navegador
Cierra el gap receta->grafo del grupo comfyui-skill. La función impura
comfyui_export_skill_template compila una skill a template API format
(exports/<slug>.template.json) y, con ui_graph=True, genera el UI graph
posicionado vía CDP (load_workflow_ui + export_workflow_ui) en la carpeta
nativa de la UI (~/ComfyUI/user/default/workflows/<slug>.json), de modo que la
skill aparece en el menú Workflows del navegador y se abre como grafo visual.
Sin navegador, deja el template API y reporta el fallback (no falla).

- 4 tests offline (golden + edge + 2 error paths).
- Página madre comfyui-skill.md: fila en la tabla del grupo + sección
  "Skills como grafos en el navegador".

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-24 16:58:11 +02:00
egutierrez 6f4b440762 feat(ml): cosecha Civitai → skills candidatas (search/fetch/extract + harvest oneshot)
Cierra la 3ª pieza del sistema comfyui-skill: cosechar de Civitai imágenes con su
workflow+receta embebidos para clonar su calidad y alimentar la librería de skills.

- comfyui_search_civitai_images: GET /api/v1/images; resuelve query->versión de
  modelo (el endpoint no admite query textual, da HTTP 500); token de pass; reintenta 503.
- comfyui_fetch_civitai_image: descarga el PNG original (conserva workflow embebido),
  SEGREGA NSFW a <dest>/nsfw/, validación no-HTML, nombre único por UUID.
- comfyui_extract_recipe_from_png: import_workflow_png + read_png_metadata + fallback
  flux (CLIPTextEncode/UNETLoader) -> receta candidata (source='civitai', score_n=0).
- comfyui_harvest_civitai_skill_oneshot (pipeline): search->fetch->extract->save_skill;
  itera items, 2º pase al feed global, NO baja modelos a ciegas (missing_models).

Hallazgo: la API de Civitai ya no expone meta (null); la receta sale del workflow
ComfyUI embebido en el PNG. Política: NSFW permitido pero SIEMPRE segregado.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-24 15:35:12 +02:00
egutierrez bcf731275e feat(ml): cierre del bucle de mejora comfyui-skill (genera→juzga→bump)
Tres funciones nuevas que cierran el lazo skill→generación→juicio→promoción
del grupo comfyui-skill (issue 0087):

- comfyui_bump_skill_version (impura): promueve una versión nueva SOLO si el
  score del panel-juez sube (gate objetivo). Snapshot versions/vN.json
  pre-mutación, deep-merge de recipe_patch, semver↑, línea en growth_log.jsonl.
  force=True salta el gate. No usa datetime.now().
- comfyui_update_skill_score (impura): media incremental de score_mean/score_n
  reescribiendo recipe.json in-place (sin snapshot ni growth_log).
- comfyui_generate_with_skill_oneshot (pipeline): one-shot load→build→submit→
  wait→fetch→judge→score_mean. recipe_patch prueba variantes sin guardar score.
  Compone 7 funciones del registry.

Tests offline: 11 passed (gate, semver, deep-merge, media incremental, errores).
Página madre docs/capabilities/comfyui-skill.md: +3 funciones, sección "Bucle de
mejora" con diagrama, fronteras de scoring actualizadas.

Demo real verificada: skill seed portrait_cinematic_sd15 (SD1.5) generó imagen
SFW real, el panel la juzgó, una variante puntuó más alto (4.787 > 4.7276) y el
gate promovió v1.0.0→v1.1.0 con el judge_run_id como evidencia.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-24 15:09:33 +02:00
egutierrez 974cc06bc7 feat(ml): panel multi-juez comfyui-judge (estetico + CLIP + LLM-vision)
Cuatro funciones impuras + pagina madre del grupo comfyui-judge, el gate
objetivo de calidad de imagen para tests/DoD y el bucle de mejora de skills:

- comfyui_score_aesthetic: estetico LAION-V2 (head MLP sobre CLIP ViT-L/14),
  subproceso al venv ComfyUI (torch+open_clip).
- comfyui_score_clip_alignment: fidelidad prompt-imagen via similitud coseno CLIP.
- comfyui_critique_image_llm: critica LLM-vision (compone ask_llm_vision), JSON
  verdict+score+reasons.
- comfyui_judge_image: agregadora, vota mayoria good/bad; degrada si un juez cae.

QuickGELU (ViT-L-14-quickgelu/openai) obligatorio: sin el, los embeddings se
degradan y el ranking de fidelidad se invierte en silencio.

Validado e2e sobre imagenes reales: golden 3 votos coherentes, asserts relativos
(nitida>ruido, alineado>desalineado), split 2-1 respeta mayoria en ambos sentidos,
degradacion ante 429/model invalido/path invalido sin crash.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-24 14:54:32 +02:00
agent 70d541fca9 feat(ml): núcleo subsistema comfyui-skill + ask_llm_vision
Grupo nuevo comfyui-skill: recetas versionadas de generación ComfyUI que
compilan a un workflow cambiando solo el subject.

- comfyui_build_skill_workflow (pura): receta -> workflow API format,
  despacha base (txt2img/flux/sdxl_refiner), sustituye {subject}+triggers,
  encadena loras e inject blocks (facedetailer, hires_fix). SkillWorkflowError tipada.
- comfyui_inject_hires_fix (pura): inyecta 2ª pasada UltimateSDUpscale sobre dict.
- comfyui_save/load/list_skill (impuras): CRUD de la librería en disco con
  versionado por snapshots, round-trip idéntico, filtro NSFW.
- ask_llm_vision (core, claude-direct): pregunta multimodal imagen+texto via
  API directa Anthropic, para puntuar generaciones.
- Página madre docs/capabilities/comfyui-skill.md con schema canónico de recipe.json.

Tests offline: 11 verdes (6 builder + 5 inject_hires_fix). Sin GPU.
2026-06-24 14:35:46 +02:00
egutierrez e8a66f0dad feat(ml): comfyui_run_foreign_workflow_oneshot + helper fetch_output_video
Pipeline one-shot para ejecutar workflows ComfyUI ajenos end-to-end
(import desde cualquier fuente -> resolve deps -> validate -> submit ->
wait -> fetch del output imagen/video/malla) componiendo 9 funciones
existentes del grupo comfyui. Gate de seguridad: si faltan nodos/modelos
NO encola y los reporta en `missing`; nunca descarga modelos a ciegas y
solo instala nodos custom confiables opt-in (install_nodes + node_repos).

Helper comfyui_fetch_output_video: hermana de fetch_output_image y
fetch_output_mesh para los nodos de video/animacion (SaveAnimatedWEBP,
SaveVideo nativo, VHS_VideoCombine). Localiza el output bajo images/gifs/
videos en /history y lo baja via /view a disco; acepta outputs= de
wait_result para evitar re-consultar /history.

Cierra la pieza marcada por el completeness critic (report 0107) del
roadmap 0064/0087. 13 tests unitarios de las partes puras en verde;
validacion de integracion contra server vivo sin generacion pesada
(report 0110).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-24 12:53:40 +02:00
egutierrez 898502a321 fix(ml): comfyui_wait_result no sale prematuro en jobs de video/3D
Exige outputs no vacios (no solo status terminal) para dar por completado
un prompt: en jobs pesados ComfyUI marca la entry de /history como
terminada antes de poblar outputs, lo que devolvia un dict vacio mientras
el job seguia en GPU. Ahora sigue sondeando hasta que los outputs aparecen
o hasta agotar el timeout. Timeout default 180s -> 600s (cubre video/3D) y
timeout HTTP por-request acotado a 30s. Firma y contrato de retorno intactos.

Tests nuevos (mock urllib CI-safe + live opcional contra /history real):
golden, regresion del bug, edge imagen corta, timeout y error. v1.0.0 -> 1.1.0.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-24 12:39:58 +02:00
egutierrez 2fe36e314e docs(ml): fix doc gap controlnet (.pth → _fp16.safetensors) + capability page comfyui completa
- comfyui_build_controlnet_workflow.md: el ejemplo usaba cn_name=control_v11p_sd15_canny.pth
  pero el modelo instalado es control_v11p_sd15_canny_fp16.safetensors. Corregido para que
  copia+pega funcione. Firma intacta.
- docs/capabilities/comfyui.md: añadida subsección "Lifecycle del server — dominio infra"
  con comfyui_ensure_server_py_infra (faltaba: página 48 vs registry 49). Ahora 49 == 49.

Higiene del grupo comfyui (report local 0104): tests de los builders puros flux/img2vid
verificados (10/10 pasan, suite del grupo 65/65), fn doctor uses-functions sin drift.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-24 12:09:04 +02:00
egutierrez 11ef8ef6db feat(ml): comfyui_build_img2vid_workflow builder img2vid SVD (API format)
Builder puro que construye el dict de un workflow ComfyUI img2vid (Stable Video
Diffusion) en API format a partir de una imagen estatica. Cadena de 7 nodos:
ImageOnlyCheckpointLoader(svd.safetensors, todo-en-uno) + LoadImage ->
SVD_img2vid_Conditioning -> VideoLinearCFGGuidance -> KSampler(denoise 1.0) ->
VAEDecode -> SaveAnimatedWEBP. SVD condiciona por CLIP_VISION de la imagen (sin
prompt de texto); movimiento via motion_bucket_id.

class_type/inputs verificados contra /object_info del servidor vivo. Validacion
estructural con comfyui_validate_workflow: 0 errores. 4 tests verdes. Sin submit
de generacion (GPU en uso por otro agente).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-24 12:02:04 +02:00
egutierrez 3e75d1bf79 feat(ml): comfyui_build_flux_workflow builder txt2img Flux (API format)
Builder puro hermano de comfyui_build_txt2img_workflow para modelos Flux
(schnell/dev): UNETLoader + DualCLIPLoader (clip_l + t5xxl, type flux) +
VAELoader -> CLIPTextEncode -> FluxGuidance + EmptySD3LatentImage ->
KSampler (cfg fijo 1.0) -> VAEDecode -> SaveImage. La guia va por FluxGuidance,
no por el cfg del sampler. fp8 + ~4 pasos para GPU de 8GB.

class_type/inputs verificados contra /object_info del server vivo. Validado
end-to-end: genera imagen real (prompt_id 909b8876, flux_builder_test_00001_.png,
status success). 6 tests unitarios verde. Pagina madre docs/capabilities/comfyui.md
actualizada con la fila del builder.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-24 11:55:09 +02:00
egutierrez 68f0ce0dae feat(infra): auto-commit con 3 cambios
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-24 11:45:31 +02:00
egutierrez c0b2dce3b0 feat(ml): auto-commit con 26 cambios
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-24 04:02:54 +02:00
egutierrez ff41f4f053 feat(ml): auto-commit con 7 cambios
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-24 02:52:51 +02:00
egutierrez f686b338d6 chore: auto-commit (14 archivos)
- docs/capabilities/comfyui.md
- python/functions/ml/comfyui_build_image_to_3d_workflow.md
- python/functions/ml/comfyui_build_image_to_3d_workflow.py
- python/functions/ml/tests/test_comfyui_build_image_to_3d_workflow.py
- python/functions/ml/comfyui_build_facedetailer_workflow.md
- python/functions/ml/comfyui_build_facedetailer_workflow.py
- python/functions/ml/comfyui_build_hires_fix_workflow.md
- python/functions/ml/comfyui_build_hires_fix_workflow.py
- python/functions/ml/tests/test_comfyui_build_facedetailer_workflow.py
- python/functions/ml/tests/test_comfyui_build_hires_fix_workflow.py
- ...

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-24 02:34:10 +02:00
egutierrez 3823a28d1c feat(ml): auto-commit con 7 cambios
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-24 02:05:43 +02:00
egutierrez 337f75b527 chore: auto-commit (5 archivos)
- docs/capabilities/comfyui.md
- python/functions/ml/comfyui_import_workflow_json.md
- python/functions/ml/comfyui_import_workflow_json.py
- python/functions/pipelines/comfyui_text_to_3d_oneshot.md
- python/functions/pipelines/comfyui_text_to_3d_oneshot.py

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-24 01:52:46 +02:00
egutierrez d3f05a19a5 feat(ml): auto-commit con 11 cambios
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-24 01:39:30 +02:00
egutierrez d7245efa59 feat(ml): auto-commit con 20 cambios
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-24 01:26:38 +02:00
egutierrez 1311c7e585 feat(ml): auto-commit con 7 cambios
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-24 01:16:37 +02:00
egutierrez f12272d002 chore: auto-commit (61 archivos)
- docs/capabilities/INDEX.md
- docs/capabilities/comfyui.md
- python/functions/browser/comfyui_export_workflow_ui.md
- python/functions/browser/comfyui_export_workflow_ui.py
- python/functions/browser/comfyui_load_workflow_ui.md
- python/functions/browser/comfyui_load_workflow_ui.py
- python/functions/browser/comfyui_queue_prompt_ui.md
- python/functions/browser/comfyui_queue_prompt_ui.py
- python/functions/browser/comfyui_refresh_nodes_ui.md
- python/functions/browser/comfyui_refresh_nodes_ui.py
- ...

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-24 00:30:30 +02:00
egutierrez f34badb500 Merge remote-tracking branch 'origin/master' 2026-06-23 17:49:49 +02:00
egutierrez bcc1fe1738 feat(captacion_clientes): scraping freelance en perfil headless dedicado, no chromium-personal
El monitor de captación scrapeaba Workana sobre el navegador personal del
usuario (chromium-personal, CDP 9222), interfiriendo con su navegación. El
scraping CDP debe correr siempre en un perfil headless dedicado.

- Nuevo pipeline monitor_freelance_projects_headless: levanta un Chromium
  headless aislado con perfil dedicado (~/.config/fn_scrape_chrome, CDP 9334)
  vía systemd-run, ejecuta monitor_freelance_projects contra ese puerto y
  cierra la instancia al terminar (finally). Reutiliza el patrón de lifecycle
  de ingest_market_trends_headless. Reutiliza un CDP vivo si el puerto ya
  responde (no cierra lo ajeno).
- scrape_workana_projects y monitor_freelance_projects: default de `port`
  cambiado de 9222 (chromium-personal) a 9334 (perfil dedicado). Default seguro:
  correr a pelo sin Chrome en 9334 falla limpio, no contamina el 9222 personal.

Verificado: el wrapper arranca headless en 9334, scrapea 8 proyectos reales de
Workana, cierra la instancia (9334 muerto, sin proceso colgado) y deja el 9222
personal intacto.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-22 20:11:26 +02:00
egutierrez 86d68dc9f0 feat(infra): conexion y consulta directa a SQL Server (Navision) via pymssql
Grupo de capacidad nuevo 'sql-connect' (3 funciones) para conectar a un
Microsoft SQL Server (donde corre Navision) y consultar directamente, en
lugar del ida y vuelta manual de pegar CSVs.

- mssql_connect_py_infra: abre conexion pymssql (login_timeout acotado,
  credenciales por argumento, RuntimeError claro si falla).
- mssql_query_py_infra: SELECT parametrizada con binding seguro (sin
  inyeccion) sobre conexion abierta; devuelve {columns, rows, row_count};
  0 filas -> lista vacia; max_rows con fetchmany; read-only.
- run_mssql_query_py_pipelines: one-shot que compone connect+query y cierra
  siempre; CLI imprime JSON o CSV; contrasena desde env var (pass).

Pagina madre docs/capabilities/sql-connect.md + fila en INDEX.md.
Dependencia pymssql>=2.3.13 anadida a python/pyproject.toml + uv.lock.
Tests mock-based (11) verdes; error path verificado end-to-end contra el
driver real (host inalcanzable -> RuntimeError, acotado por login_timeout).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-22 11:29:49 +02:00
egutierrez 3cf8b21fea feat(datascience): promover remove_background al registry + mask en depth_to_relief_glb (grupo img-to-3d)
Completa la promoción del flujo imagen->3D al registry (grupo de capacidad
img-to-3d), extraído de la app img_to_3d_webapp.

- remove_background_py_datascience (nueva): elimina el fondo con cascada
  rembg/U2Net -> OpenCV GrabCut -> umbral NumPy, compone el objeto sobre gris
  neutro y devuelve image + mask + engine. Impura, nunca lanza. Adaptada de
  backend/bg_removal.py con firma de ruta (image_path) y salida dict, demo CLI
  JSON-serializable.
- depth_to_relief_glb_py_datascience (v1.1.0): añade el parámetro opcional mask
  para recortar la malla de relieve al objeto (descarta las caras del fondo),
  cerrando la cadena con remove_background. Aditivo (mask=None = comportamiento
  previo), fiel al original de backend/depth.py.
- docs/capabilities/img-to-3d.md: incorpora remove_background como paso 0
  (pre-proceso), actualiza el flujo a 3 pasos encadenados, la tabla de funciones
  (4), el ejemplo end-to-end con mask y las deps (rembg/opencv).
- docs/capabilities/INDEX.md: conteo del grupo 3 -> 4.

Las dos funciones ya presentes (estimate_image_depth, depth_to_relief_glb) y el
pipeline build_relief_glb_from_image fueron promovidas en una ronda previa.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-21 21:43:08 +02:00
egutierrez e4a36f1133 chore(tags): anadir tag 'orchestration' a las 6 funciones del grupo que faltaban
capability_groups.md exige que toda funcion de un grupo lleve su tag plano para
ser descubrible via fn_search tag='orchestration'. 6 de las funciones del grupo
(reboot_all_claudes, classify_fleet_termination, list_claude_fleet,
drain_fleet_events, mark_claude_role, set_dod_contract) no lo llevaban. Se anade
sin borrar los tags existentes.

notify_desktop_go_infra ya llevaba el tag pero no figuraba en la tabla del grupo:
se decide que SI pertenece (la usa el orquestador/watcher para avisar de un
RECLAMA u otro evento urgente) y se anade a la tabla en orchestration.md (commit
anterior), en lugar de quitarle el tag. Resultado: 13 funciones con tag
orchestration, identicas a las 13 filas de la tabla del grupo (sin drift).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-21 18:03:14 +02:00
egutierrez 32c7336bf6 feat(infra): auto-commit con 56 cambios
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-21 14:22:55 +02:00
egutierrez 753e16b84c feat(infra): mark_claude_parent — escribe parent_orchestrator en goal.json (PID->sessionId)
Helper py analogo a mark_claude_role: resuelve el sessionId de un Claude recien
arrancado por su PID (sondeando sessions/<pid>.json) y escribe SOLO la clave
parent_orchestrator en su goal.json, preservando el resto. Lo consume
spawn_fleet_agent --parent para que el watcher de fleetview rutee los avisos del
ejecutor a su orquestador padre. Tests: escribe+preserva, goal inexistente,
parent vacio (ValueError), timeout sin crash.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-21 13:27:47 +02:00
agent 118d5d36d3 feat(orquestador): feed reactivo FLEET-STATE + fix peek de drain_fleet_events
El orquestador no se enteraba de los cambios de estado de su flota: el drenado
era manual y el peek documentado `./fn run drain_fleet_events --advance false`
devolvia un falso `{total_new:0, cursor:0}` porque `fn run` mapea los argumentos
posicionalmente y no parsea flags `--nombre valor` (events_path acababa valiendo
"--advance", una ruta inexistente).

- drain_fleet_events: nuevo helper _normalize_fn_run_flags que renormaliza el
  patron `--advance <bool>` aplanado por `fn run`, de modo que el peek funciona
  directo desde la CLI sin tocar el runner de Go. Bump 1.1.0 + growth log + tests
  del normalizador (unit y end-to-end por HOME).
- summarize_fleet_transitions (nueva, pure, grupo claude-fleet): resume el dict
  by_classification de drain en un bloque de una linea con las tres categorias
  accionables (terminados / reclaman / estancados), dedup por session_id y
  truncado de objetivo.
- hook_fleet_state_inject.sh (UserPromptSubmit): si la sesion es role=orchestrator
  (leido de ~/.claude/goals/<session_id>.json), hace peek de la cola sin mover el
  cursor y emite el bloque FLEET-STATE cada turno. Degrada limpio si el watcher
  esta caido, la cola no existe o la sesion no es orquestador.

El registro del hook va en .claude/settings.local.json (gitignored, fuera de este
commit). Pendiente, lo integra otro agente: documentar el bloque FLEET-STATE en
.claude/commands/orquestador.md.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-21 00:06:01 +02:00
agent 334a71eed1 feat: launcher arranca orquestador + idle, pin por role (flow 0012, fase 3b)
- mark_claude_role (python/functions/infra): resuelve PID->sessionId
  esperando sessions/<PID>.json y escribe role en el goal.json sin pisar
  el resto. 4 tests.
- launch_fleetclaude: el pane derecho arranca el ORQUESTADOR con el skill
  /orquestador embebido como primer prompt; tras arrancar, mark_claude_role
  le pone role=orchestrator (en background, no-fatal) para que la TUI lo
  pinee arriba; ademas siembra 1 ejecutor idle inicial en su propia window.
- skill /orquestador: regla 'no te vigiles a ti mismo' (ignora en la cola
  su propia sesion y cualquier role=orchestrator).

Validado en vivo (perfil aislado): claude /orquestador entra en modo,
role marcado, idle sembrado, pin correcto, fleet2 intacto.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-20 20:33:37 +02:00
agent 9365def3dd feat: cerebro reactivo del meta-orquestador (flow 0012, fase 2)
Primitivas (python/functions/infra):
- drain_fleet_events: consume la cola del watcher (~/.claude/fleet/
  events.jsonl) desde un cursor, agrupa por clasificacion, marca
  urgentes. 7 tests.
- set_dod_contract: escribe el DoD-contrato fijo (dod_contract/dod_status)
  en el goal.json de un agente sin pisar el resto (escritura atomica).
  5 tests.

Skill /orquestador evolucionado (sin romper lo existente): vigila la
flota por su DoD (no por 'esta vivo'). Nueva seccion 'Consumo de la cola
de la flota': DoD-contrato obligatorio al lanzar, drenar la cola,
politicas por clasificacion (RECLAMA escala / DICE_TERMINADO verifica /
ESTANCADO nudge / MAL_LANZADO re-DoD), verificador independiente del
ejecutor (lee el report vs dod_contract), splitter con tope de fan-out,
y cadencia (drain al actuar + heartbeat).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-20 20:19:26 +02:00
egutierrez 763e06c127 feat(browser): auto-commit con 178 cambios
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-20 18:22:23 +02:00
egutierrez 6ab85ee701 Merge remote-tracking branch 'origin/master' 2026-06-17 10:30:27 +02:00
egutierrez 909290ddbf feat(infra): auto-commit con 8 cambios
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-17 10:30:26 +02:00
egutierrez 927437a8d8 feat(infra): grupo claude-fleet — FleetView TUI + orquestacion de Claudes
Sistema FleetView para centralizar la flota de procesos Claude Code vivos en una
sola ventana kitty + tmux (socket aislado -L fleet) con un panel TUI:

- list_claude_fleet (+ tipo claude_fleet): escanea ~/.claude/sessions + goals +
  runtime, valida procesos vivos (anti-PID-reciclado), join por sessionId.
- list_resumable_claudes (+ tipo resumable_claude): sesiones cerradas reanudables.
- wrappers tmux: tmux_new_claude_window (con --resume), tmux_swap_window_into_console
  (preserva ancho del sidebar), tmux_map_claude_panes.
- launch_kittyclaude: comando entrypoint; instala atajos alt+flechas/enter/n/0/k/r,
  mouse on, remain-on-exit off; fija el ancho del sidebar con hooks.
- docs/capabilities/claude-fleet.md + entrada en el INDEX.

Incluye ademas funciones datascience en progreso (excel/duckdb/postgres) y ajustes
varios de docs e infra de otra sesion, agrupados aqui para no perderlos.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-17 00:04:41 +02:00
egutierrez 588d092858 docs(infra): add .md metadata for write_xlsx_sheets function
The function code and its registry metadata were created together but the
.md was left untracked by the auto-commit. Add it so the indexed function
has its companion metadata versioned.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-15 01:35:42 +02:00
egutierrez a90b7443e4 cuando termines y verifica que esté todo subido
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-15 01:33:35 +02:00
egutierrez e1e9bb7499 feat(shell): auto-commit con 31 cambios
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-14 23:55:16 +02:00
egutierrez 1430039688 feat(recon): modo CDP en fingerprint_web_stack para detectar SPAs
Añade fetch_http_fingerprint_cdp_py_browser (domain browser): recoge el HTML
renderizado tras ejecutar JavaScript usando un Chrome remoto via CDP, componiendo
cdp_open_url_and_wait + cdp_eval. Devuelve la misma estructura que el fetch
estático para que detect_web_tech lo consuma sin cambios.

Integra use_cdp en el pipeline fingerprint_web_stack (v1.1.0): combina los headers
reales del fetch estático con el HTML post-JS del CDP. Detecta frameworks de SPA
(React/Vue/Angular/Next) que el fetch estático no ve porque montan el DOM en
runtime. Si no hay Chrome en cdp_port, degrada al fetch estático con un warning
(no rompe). cdp_port=9333 (Chrome aislado) recomendado para terceros, 9222 diario.

Verificado en vivo (Chrome 9333): sobre una SPA cuyo marcador de framework solo
aparece tras ejecutar JS, el estático detecta solo nginx; con use_cdp=True detecta
además Next.js, React y Node.js.

Tests: 48 verdes (error path sin Chrome + happy path mockeado + degradación).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-14 15:31:28 +02:00
egutierrez 935008ec3f feat(recon): grupo de reconocimiento de red + servicios + fingerprint web
Añade el capability group `recon` (dominio cybersecurity + pipelines, Python),
con la política de archivado OSINT y página madre docs/capabilities/recon.md.

Lookups y sondeo (wrappers de CLI):
- whois_lookup, rdap_lookup, dns_records, ping_host, traceroute_host, nmap_scan
- save_scan_to_osint (sink común) + recon_osint (pipeline one-shot scan+archivado)

Escaneo de puertos/servicios nativo (stdlib, sin nmap ni sudo):
- scan_tcp_ports: connect-scan TCP concurrente (open/closed/filtered)
- grab_service_banner: banner grab + identificación de servicio/versión real
- identify_port_service: puro, puerto -> servicio IANA esperado (~120 puertos)
- scan_port_services: pipeline one-shot (scan -> identify + banner por puerto abierto)

Fingerprint de tecnología web (estilo Wappalyzer), patrón pura/impura:
- fetch_http_fingerprint: GET stdlib, recoge headers/html/cookies (solo nombres)
- detect_web_tech: puro, matchea ~50 firmas regex -> tecnologías por categoría
- fingerprint_web_stack: pipeline one-shot url -> tecnologías

Todas devuelven dict {status} sin lanzar. Tests: 43 verdes, sin red externa.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-14 15:12:07 +02:00
egutierrez d89da1292d chore: auto-commit (9 archivos)
- docs/capabilities/INDEX.md
- docs/capabilities/obsidian.md
- python/functions/core/render_markdown_table.md
- python/functions/core/render_markdown_table.py
- python/functions/core/render_markdown_table_test.py
- python/functions/core/upsert_sentinel_block.md
- python/functions/core/upsert_sentinel_block.py
- python/functions/core/upsert_sentinel_block_test.py
- python/functions/infra/duckdb_query_readonly.md

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-13 21:56:56 +02:00
egutierrez 167a7e5eb7 feat(core): contact_import_key — clave de importacion determinista de contactos
Hash estable (tel normalizado > email > nombre normalizado) para importaciones
idempotentes: re-importar el mismo .vcf matchea la fila existente sin depender de
UIDs opacos ni de nombres que el pipeline de import transforma. Prefijo v1- para
versionar el algoritmo. Funcion pura + 5 tests.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-13 11:47:48 +02:00
egutierrez b8ec97e477 fix(security): build_vcard neutraliza el retorno de carro crudo (anti CR-injection vCard)
El escape de valores vCard solo escapaba el salto de linea, no el retorno de
carro crudo. Un \r sin \n sobrevivia al escape y los parsers que lo normalizan
a salto de linea (como _unfold_lines de osint_web) leian propiedades inyectadas
(p.ej. X-OSINT-DNI), burlando el control de no exponer datos OSINT al movil.
Ahora _vcard_escape elimina el \r, en paridad con el escape iCal. Test de
regresion anadido.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-13 11:19:43 +02:00
egutierrez 40400c0b88 fix(security): duckdb_query_readonly sandbox por defecto (enable_external_access=false)
CRÍTICO: read_only=True protege la base de datos pero NO el sistema de ficheros. Un
SELECT con read_csv/read_blob/glob/COPY...TO podía leer ficheros arbitrarios (claves SSH)
o escribirlos (camino a RCE). Añadido parámetro sandbox (default True) que abre la conexión
con enable_external_access=false, bloqueando todo acceso a FS/red desde la query. Los SELECT
normales sobre tablas siguen funcionando. Único consumidor (osint_db /api/query) queda
protegido sin cambios. Tests nuevos: sandbox bloquea read_csv; sandbox=False lo permite.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-13 01:21:01 +02:00
egutierrez 236a4740b0 fix(dav): error_type en dav_make_addressbook/dav_make_calendar (impure requiere error_type)
El indexer rechaza funciones impure con error_type vacío. Ambas funciones del grupo dav
declaran error_go_core como el resto de las funciones DAV Python del registry.
2026-06-13 00:45:00 +02:00
egutierrez 1c4a4b9259 feat(duckdb,dav): primitivas de escritura DuckDB + libretas CardDAV + vCard multi-valor
Cinco funciones nuevas para soportar DuckDB como fuente de verdad del project osint:

Grupo duckdb (escritura, complementan a duckdb_query_readonly):
- duckdb_execute_py_infra (impure): ejecuta INSERT/UPDATE/DELETE/DDL en read-write, commit, {status,rowcount}. 6 tests.
- duckdb_upsert_py_infra (impure): UPSERT ON CONFLICT actualizando solo update_cols → ownership selectivo (un re-upsert no pisa columnas excluidas). 7 tests.

Grupo dav (libretas de contactos + vCard multi-valor):
- dav_make_addressbook_py_infra (impure): crea una libreta CardDAV nueva via extended MKCOL (RFC 5689). Idempotente. 12 tests.
- dav_list_addressbooks_py_infra (impure): lista las libretas del contacts-home (PROPFIND Depth:1). 7 tests.
- build_vcard_py_core (pure): serializa un contacto a vCard 3.0 multi-valor (N TEL/EMAIL/ADR + X-OSINT-*). 5 tests.

Paginas de capacidad duckdb.md y dav.md actualizadas.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-13 00:33:12 +02:00