--- id: "0109h" title: "skill_tree: generar ideas con LLM y promover a issue/flow desde la interfaz" status: in-progress type: feature domain: - meta - cpp-stack scope: app-scoped priority: alta depends: - "0109b" blocks: [] related: - "0109" - "0085" - "0086" created: 2026-05-17 updated: 2026-05-17 tags: - skill-tree - cpp - imgui - llm - claude-cli - ideas - ghost-nodes --- # 0109h — Generate ideas + promote to issue/flow ## UX que el usuario quiere Click en cualquier nodo del Tree → Inspector aparece con boton `[ ⨁ Generate ideas ]`. Click ese boton → 1. Skill_tree lanza `claude -p ""` en background. 2. LLM devuelve N (3-5) ideas JSON con `{title, description, type: issue|flow, domain}`. 3. Cada idea aparece como un **ghost-node** (nodo semi-transparente con outline animado) que **emerge del nodo source** y se anima hacia su target ring/sector segun su domain. 4. Click sobre el ghost → Inspector pivota al draft. Muestra title + description + buttons: - `[ + Generate issue ]` (technical — escribe `dev/issues/NNNN-.md`) - `[ + Generate flow ]` (use-case — escribe `dev/flows/NNNN-.md`) - `[ × Discard ]` (elimina del buffer) 5. Si el usuario promueve → archivo creado, draft eliminado, F5 (auto-trigger) recarga y el nodo aparece como nodo real con ID nuevo. ## Modelo ### Ghost-node ```cpp struct DraftNode { std::string id; // tmp_ std::string source_id; // ID del nodo que la genero std::string title; std::string description; std::string proposed_type; // "issue" or "flow" std::string proposed_domain; std::string proposed_priority; std::vector proposed_depends; std::vector proposed_dod_items; float x = 0, y = 0; // posicion actual (lerp) float target_x = 0, target_y = 0; double spawn_t = 0; // animacion 1s emerge }; ``` Buffer global `g_drafts` (en memoria, NO persistido — drafts viven hasta promote o discard, sin persistencia entre runs). ### Spawn LLM `spawn_claude_p_for_ideas(node)`: - Construye prompt: ``` Eres un asistente que propone sub-tareas para el sistema fn_registry. Contexto del nodo origen: ID: 0109b Title: skill_tree layout anillos Status: completado Domain: meta, cpp-stack Type: feature Body: Proponme 3-5 ideas de sub-tareas (issues tecnicas o flows de uso) que extiendan o validen lo logrado por este nodo. Para cada idea devuelve JSON: { "title": "...", "description": "...", "type": "issue|flow", "domain": "", "priority": "alta|media|baja", "depends": [], "dod": ["..."] } Devuelve SOLO un array JSON, sin texto extra. ``` - `claude --print ""` con timeout 60s. stdout capturado en pipe. - Parse JSON array → cada elemento se convierte en `DraftNode`. ### Promote `promote_draft_to_issue(draft, output_dir)`: - Encuentra siguiente NNNN libre escaneando `dev/issues/`. - Renderiza frontmatter YAML desde template + body. - Escribe `dev/issues/NNNN-.md`. - Quita `draft` de `g_drafts`. - Trigger `reload_scan()`. Similar para flows en `dev/flows/`. ## Sub-issues - **0109h1** — Framework ghost-nodes (sin LLM, mock con datos hardcoded): Render + animacion + Inspector + promote. - **0109h2** — Integracion claude -p real: spawn async, parse JSON, fill drafts. - **0109h3** — Loading indicator + cancel. - **0109h4** — Rate-limit: 1 invocacion por nodo por hora (`last_request_t` en draft buffer). ## Riesgos - **claude -p timeout**: respuestas >60s posibles. Mitigacion: async + ImGui spinner. - **JSON malformado**: el modelo a veces devuelve markdown alrededor del JSON. Mitigacion: extraer entre primeras `[` y ultimas `]`, retry parsing. - **Costo**: cada invocacion consume tokens. Mostrar contador de invocaciones en sesion (`g_llm_calls_count`). - **Promote a archivo escribe en `dev/issues/` que NO es sub-repo**: ese write toca fn_registry main repo. OK porque dev/issues/ es parte del registry. Pero requiere que skill_tree.exe tenga permiso de escritura — en Windows con paths WSL `\\wsl$\Ubuntu\home\lucas\fn_registry\dev\issues\` debe funcionar. ## DoD - [ ] Boton Generate ideas en Inspector lanza spawn LLM. - [ ] Drafts aparecen como ghost-nodes en el canvas con animacion emerge. - [ ] Click ghost → Inspector pivota a draft. - [ ] Buttons Generate issue / Generate flow escriben .md a disco. - [ ] Reload F5 (o auto-trigger tras escribir) muestra el nuevo nodo en el canvas. - [ ] Discard elimina draft del buffer. - [ ] Rate-limit suave (1 invocacion / nodo / hora).