Bug derivado del fix anterior: gx-cli escribia ficheros JSON en
`$GX_APP_DIR/agent_jobs_queue/` (apuntando al repo fuente) mientras
main.cpp escaneaba `parent(g_layout_db_path)/agent_jobs_queue/`
(install Windows). Dos directorios distintos -> jobs huerfanos.
Echo reportaba "encolado" pero el worker nunca veia los ficheros.
La causa: chat.cpp setea GX_APP_DIR=<registry>/projects/osint_graph/
apps/graph_explorer y GX_APP_DB=<install>/local_files/projects/<slug>/
graph_explorer.db. Dos sitios. Solo APP_DB coincide con donde
graph_explorer.exe escanea (parent del .db).
Fix:
* gx-cli cmd_enricher_run: queue_dir = parent(GX_APP_DB) /
agent_jobs_queue. Alineado con main.cpp.
* gx-cli: nuevo helper `_log(tag, msg)` que escribe a stderr Y a
`<parent(app_db)>/gx-cli.log` para auditoria persistente. Cubre
node_create, node_update, node_delete, rel_create, enricher_run.
* gx-cli mcp _mcp_log tambien persiste a gx-cli.log.
* main.cpp: log el queue scan dir una vez por sesion para detectar
mismatches a futuro.
* .gitignore: agent_jobs_queue/ y gx-cli.log son runtime, no se
commitean.
Tests:
* test_enricher_run_queue_dir_derives_from_app_db (regresion)
configura GX_APP_DB en un dir distinto de GX_APP_DIR y verifica
que el JSON aterriza junto a APP_DB.
* test_enricher_run_writes_log_to_gx_cli_log valida la auditoria.
WSL 81 / Windows 70 + 11 skipped.
Bug: Echo (gx-cli en WSL) recibia "disk I/O error" al INSERT en la
tabla `agent_jobs` de graph_explorer.db. Causa: graph_explorer.exe
mantiene esa BD abierta con journal_mode=WAL desde Windows, y SQLite
WAL exige mmap del .shm compartido entre procesos. Cuando un escritor
accede via /mnt/c (9p) y el otro nativo NTFS, ese mmap falla.
El proyecto ya habia resuelto este patron antes: el contador de
mutaciones (.mutations.marker) usa fichero plano en vez de SQL por
exactamente la misma razon. agent_jobs era la unica cola que se
quedo en SQLite — momento de aplicar el mismo fix.
Cambios:
* gx-cli cmd_enricher_run: en lugar de INSERT, escribe
`<app_dir>/agent_jobs_queue/<req_id>.json` con el payload del job.
Atomic write (tmp + rename, atomico tanto en NTFS como en 9p).
* main.cpp polling: en lugar de SELECT/DELETE sobre agent_jobs,
escanea ese directorio cada frame, lee cada JSON via json_extract
(sqlite3 in-memory, sin tocar archivos en disco), llama jobs_submit,
y borra el fichero. Throttle a 8 jobs por frame igual que antes.
* main.cpp: anyade <filesystem> y <fstream>.
* tests/test_gx_cli.py: 5 tests nuevos en TestCliEnricherRun:
- escribe fichero JSON con req_id como nombre
- NO crea tabla agent_jobs en graph_explorer.db (regresion)
- errores claros si enricher o nodo no existen
- no quedan .tmp tras encolado exitoso
WSL 79 / Windows 68 + 11 skipped.
Bug encontrado por el agente Echo: el MCP server gx-cli (subcomando
`mcp-server`) llamaba a cmd_node_create / cmd_node_update con un
SimpleNamespace que NO incluia `notes`, asi que `args.notes` lanzaba
AttributeError. Causa raiz: MCP_DISPATCH no defaulteaba `notes` ni
`append_notes`, y el inputSchema de las tools tampoco los anunciaba.
Cambios:
* MCP_TOOLS["node_create"].inputSchema.properties anyade `notes`.
* MCP_TOOLS["node_update"].inputSchema.properties anyade `notes`
+ `append_notes` (boolean, default false).
* MCP_DISPATCH["node_create"] defaultea `notes: None`.
* MCP_DISPATCH["node_update"] defaultea `notes: None`,
`append_notes: False`.
Tests nuevos en tests/test_gx_cli.py (30 tests):
* CLI: node create/update/delete con notes (replace + append),
list/show/search, rel create/list/delete con cascada, query
read-only que rechaza writes, autodetect de tipos.
* MCP dispatcher: cada cmd_* tolera args opcionales omitidos,
notes y append_notes funcionan via dispatch, MCP_TOOLS y
MCP_DISPATCH coinciden 1:1 (sanity contractual).
* Regresion 0035d: tests dedicados que congelan el contrato
notes/append_notes en defaults e inputSchema — si alguien
vuelve a quitarlos el test se queja inmediatamente.
WSL 74 / Windows 63 + 11 skipped.