El campo `notes` es lo que el usuario escribe en el panel Note del
Inspector (doble click sobre el nodo) — sitio canonico para texto
largo. Antes los enrichers leian metadata.text/description/query como
prioridad, dejando notes ignorado y forzando al usuario a inyectar
texto via la UI metadata-extra (poco descubrible).
Cambios:
- Ambos run.py abren la BD y leen `entities.notes` por SQL antes de
fallback a node_name. metadata.text/description/query ya no se
consultan (KISS — solo notes y name).
- conftest.make_node admite kwarg `notes` para inyectar contenido
en la columna notes desde tests.
- Tests actualizados: SAMPLE_TEXT y los IoC dumps van por `notes=`
en lugar de `metadata={"text": ...}`.
- Renombrado el test que verificaba prioridad: ahora se llama
`*_uses_notes_priority` y verifica notes > name.
Tests verdes WSL (44) y Windows (33 + 11 skipped).
Bloque de cambios revisados y validados con el usuario en sesiones
previas que no habian aterrizado en commits propios. Lista por tema:
* enrichers: web_search ahora usa lite.duckduckgo.com como endpoint
primario (mas tolerante con bot detection desde IP residencial),
con fallback al endpoint html. Detecta pagina captcha y emite
error claro si ambos fallan. Anyade _DDGLiteParser para el formato
lite + auto-pick de parser por contenido.
* enrichers: tipo Webpage unificado en Url (campos de cuerpo
cacheado viven en metadata del Url). Manifests actualizados
(applies_to: [Url]). fetch_webpage ya no convierte Url->Webpage.
* enrichers/manifest: campo `params` parseado a EnricherSpec.params
(name, type, default_value, description). UI puede renderizar
dialog de configuracion.
* jobs: fix de path conversion para Python embebido nativo Windows
(no convertir a /mnt/c/... cuando el subproceso es Windows-native;
solo cuando es bash o python via WSL).
* main.cpp: ventana ImGui (no modal) "Run enricher" con layout
2-col (label izq, input der). Inserta job con JSON tipado. Layout
clustering apretado: hijos del mismo anchor en un solo anillo
alrededor del padre, sin desperdigar por anillos crecientes.
* views: inspector con layout 2-col via BeginTable (Identity,
Schema fields, Extras). Description full-width debajo de su label.
* tests: portable conftest (auto-detecta REGISTRY_ROOT, PYTHON_BIN,
ENRICHERS_DIR para WSL y Windows portable). _runner.py trampoline
inyecta stub via sys.path porque embedded Python ignora PYTHONPATH.
Tests bash-only (vendor_script, freeze, dispatcher bash, resolver
Linux-binary) skipean en Windows. Tests existentes adaptados a
Webpage->Url.
Resultado actual: 32 passed WSL, 21 passed + 11 skipped Windows.
Anade enricher web_search aplicable a nodos text/Concept/Topic. Hace
POST a html.duckduckgo.com con la query del nodo, parsea resultados
con HTMLParser stdlib, decodifica el redirect uddg= y crea N nodos
Url con relacion SEARCH_RESULT_OF apuntando al nodo origen.
Encadenable: tras web_search, fetch_webpage sobre cada Url completa
el pipeline search -> fetch -> extract.
Defensa contra ops_db_path mal resuelto: normaliza backslashes,
resuelve relativo contra app_dir, valida que la tabla entities
exista antes de tocar nada (exit codes 7/8/9 con JSON resumen).
Tests pytest (16/16 verde): conftest con operations.db temp +
schema minimo, stub de requests via PYTHONPATH para mockear red.
Cubre los 5 enrichers (extract_domain, fetch_webpage, extract_links,
extract_text_entities, web_search) + sanity check de manifests.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>