diff --git a/.claude/commands/issue.md b/.claude/commands/issue.md new file mode 100644 index 00000000..5aa0a386 --- /dev/null +++ b/.claude/commands/issue.md @@ -0,0 +1,93 @@ +--- +description: "Gestiona issues del registry en dev/issues/. Subcomandos: list, show, status, board, dep, roadmap, tag, done, stale, create. Frontmatter YAML canonico (issue 0100)." +--- + +# /issue — Gestionar issues del registry + +Issues viven en `dev/issues/NNNN-.md` con frontmatter YAML canonico (id, title, status, type, domain, scope, priority, depends, blocks, related, created, updated, tags). + +Allowlists en `dev/TAXONOMY.md` (no inventar valores). + +Diferencia con `dev/flows/`: +- **Issues** = bugs, features, refactors, chores, epics de implementacion. +- **Flows** = casos de uso end-to-end multi-app. + +## Sintaxis + +``` +/issue list [--domain X] [--type Y] [--status Z] [--prio P] [--epic NNNN] +/issue show NNNN +/issue status NNNN # acceptance % + estado deps +/issue board # kanban pendiente/in-progress/bloqueado/done +/issue dep NNNN # arbol bloquea/depende +/issue roadmap NNNN # epic + sub-IDs (NNNNa, NNNNb, ...) +/issue tag NNNN +X -Y # mantenimiento tags/domain +/issue done NNNN # mueve a completed/, valida deps +/issue stale [--days 30] +/issue create --type T --domain D [--prio P] [--depends NNNN] +``` + +## Implementacion + +**Fase 1 (manual via Claude):** + +El agente lee `dev/issues/*.md`, parsea frontmatter YAML con `yaml.safe_load`, aplica el filtro, imprime tabla. + +```python +import yaml, pathlib, re +issues = [] +for f in pathlib.Path("dev/issues").glob("*.md"): + if f.name in {"README.md", "template.md"}: continue + txt = f.read_text() + m = re.match(r"^---\n(.*?)\n---", txt, re.S) + if not m: continue + fm = yaml.safe_load(m.group(1)) or {} + fm["_path"] = str(f) + issues.append(fm) +# filter + print +``` + +**Fase 2 (cuando 0101 dev_console exista):** + +Cada subcomando se mapea a `./apps/dev_console/dev_console issue $ARGS`. + +## Subcomandos clave + +### `list` + +Imprime tabla `id | title | status | type | domain | priority | depends_pending`. Filtrable por flags. + +### `show NNNN` + +Read directo del .md + render del frontmatter como tabla + body como markdown. + +### `status NNNN` + +Cuenta checkboxes en `## Acceptance` + chequea si todos los `depends` estan en `status: completado`. Si alguno no, marca `bloqueado`. + +### `board` + +Tabla 4 columnas (pendiente / in-progress / bloqueado / completado_hoy). Card por issue: id + title + prio. Status `bloqueado` se calcula on-the-fly desde `depends`. + +### `roadmap NNNN` + +Si `type: epic`: lista sub-issues `NNNNa`, `NNNNb`, etc. con su estado. Si no epic: error "not an epic". + +### `done NNNN` + +1. Lee frontmatter. +2. Verifica todos `depends` cerrados (sino, error). +3. Cuenta `## Acceptance` 100% (sino, error). +4. `git mv dev/issues/NNNN-*.md dev/issues/completed/`. +5. Actualiza `status: completado` + `updated: today`. + +### `create --type T --domain D` + +Genera siguiente ID libre (max existing + 1, zero-padded 4). Scaffold desde plantilla minima con frontmatter rellenado. + +## Reglas + +- Domain debe estar en `dev/TAXONOMY.md` allowlist. +- Scope/type/priority idem. +- `id` siempre string `"NNNN"` (zero-padded, sub-IDs con sufijo `a-z`). +- Modificar frontmatter SIEMPRE preserva campos no tocados (no overwrite). diff --git a/.claude/commands/work.md b/.claude/commands/work.md new file mode 100644 index 00000000..75e54d29 --- /dev/null +++ b/.claude/commands/work.md @@ -0,0 +1,67 @@ +--- +description: "Vista cross-cutting de issues + flows. Subcomandos: today, weekly, search, dashboard. Mezcla los dos universos en una lista priorizable." +--- + +# /work — Vista cross-cutting issues + flows + +Issues = trabajo de implementacion. Flows = casos de uso multi-app. `/work` los muestra juntos para responder "que hago ahora" sin saltar entre dos sitios. + +## Sintaxis + +``` +/work today # top items prio alta + deps satisfechas (issues + flows) +/work weekly # review semanal: closed vs planeados +/work search "texto" # FTS sobre issues + flows + completed +/work dashboard # JSON consumible por tab Work (issue 0102) +``` + +## Implementacion + +**Fase 1 (manual via Claude):** + +El agente lee `dev/issues/*.md` + `dev/flows/*.md`, parsea frontmatter YAML, ordena por: + +1. `priority: alta` primero. +2. `status: pendiente` con `depends` todos `completado` (no bloqueados). +3. Items con DoD/Acceptance >=80% (a punto de cerrar). +4. Fecha `updated` mas reciente. + +Imprime tabla unificada: + +``` +KIND | ID | TITLE | PRIO | STATUS | NEXT STEP +issue| 0099 | datahub app launcher | alta | pendiente | revisar deps +flow | 0001 | hn-top-stories | high | pending | cerrar DoD user-facing +issue| 0100 | migrate issue frontmatter | alta | pendiente | ejecutar pipeline +... +``` + +**Fase 2 (cuando 0101 dev_console exista):** + +`./apps/dev_console/dev_console work $ARGS`. + +## Subcomandos + +### `today` + +Filtro: `priority in (alta, media)` + `status: pendiente` + dependencias resueltas. Max 10 items. Si hay >10, prioriza `alta` y avisa "N items pendientes en cola". + +### `weekly` + +Git log `--since='1 week ago'` sobre `dev/issues/completed/` y `dev/flows/completed/` -> tabla de items cerrados. Comparado con `created: ` -> ratio in/out. + +### `search "texto"` + +`grep -ri` sobre `dev/issues/` + `dev/flows/` (incluido completed/), filtra por title/body. Output: `path:line: match`. + +### `dashboard` + +Output JSON estructurado para consumo por tab Work del `registry_dashboard` (issue 0102). Estructura: + +```json +{ + "issues": {"pendiente": [...], "in-progress": [...], "bloqueado": [...], "completado_24h": [...]}, + "flows": [{"id": "0001", "dod_percent": 50, "user_facing_percent": 0, "...": ...}], + "telemetry": {"calls_24h": N, "violations_24h": N, "pending_proposals": N} +} +``` diff --git a/.claude/rules/INDEX.md b/.claude/rules/INDEX.md index b541a86c..6d0e71bc 100644 --- a/.claude/rules/INDEX.md +++ b/.claude/rules/INDEX.md @@ -35,3 +35,4 @@ Reglas operativas del proyecto. Cada archivo es una regla independiente. | 29 | [capability_groups.md](capability_groups.md) | Tags planos + paginas madre `docs/capabilities/.md` para desbloquear clusters de funciones en un read. Issue 0086 | | 30 | [function_growth_and_self_docs.md](function_growth_and_self_docs.md) | Contrato self-doc de cada `.md` (Ejemplo + Cuando usarla + Gotchas + Growth log) + crecimiento del registry por **promocion de composiciones** a pipelines, NO por inflado de funciones. Issue 0087 | | 31 | [autonomous_loop.md](autonomous_loop.md) | Reglas para `fn-orquestador` + `/autonomous-task`: sandbox obligatorio, paths protegidos, filtro proposals auto-aplicables, watchdog, idempotencia. Issue 0069 | +| 32 | [../../dev/TAXONOMY.md](../../dev/TAXONOMY.md) | Allowlist canonica para dominios/tipos/scopes/estados/prioridades + flow patterns. Aplica a `dev/issues/` y `dev/flows/`. Issues 0100 + 0103 | diff --git a/.gitignore b/.gitignore index 0f36ec04..07e1d17f 100644 --- a/.gitignore +++ b/.gitignore @@ -85,3 +85,6 @@ kotlin/functions/ui/ # Module versioning auto-generated headers (written by `fn index`, issue 0097) **/version_generated.h **/app_modules_generated.h + +# Issue migration backups (0100) +dev/issues/.backup_pre_* diff --git a/bash/functions/infra/deploy_cpp_exe_to_windows.md b/bash/functions/infra/deploy_cpp_exe_to_windows.md index 75a7b086..4254fe86 100644 --- a/bash/functions/infra/deploy_cpp_exe_to_windows.md +++ b/bash/functions/infra/deploy_cpp_exe_to_windows.md @@ -3,7 +3,7 @@ name: deploy_cpp_exe_to_windows kind: function lang: bash domain: infra -version: "1.0.0" +version: "1.1.0" purity: impure signature: "deploy_cpp_exe_to_windows(app_name: string, app_dir: string) -> void" description: "Copia el .exe de Windows (compilado por build_cpp_windows) y sus assets al escritorio de Windows /mnt/c/Users/lucas/Desktop/apps//. Mata el proceso si esta corriendo (taskkill.exe pre-autorizado), copia DLLs, sincroniza assets/ y enrichers/ con rsync, maneja runtime Python embebido si python_runtime: true en app.md, y copia extras gx-cli. Preserva siempre local_files/ (estado del usuario)." @@ -63,3 +63,8 @@ Desktop/apps// - `rsync --delete` en assets/ y enrichers/ para mantener destino limpio. - Si `python_runtime: true` en `app.md` y `runtime/.lock` es mas antiguo que `app.md`, invoca `tools/freeze_python_runtime.sh` automaticamente. - `local_files/` jamas se toca: contiene estado per-PC del usuario (DBs SQLite, ImGui layouts, settings). + +## Capability growth log + +v1.1.0 (2026-05-17) — Bugfix: el `cp` del .exe no chequeaba exit status y la funcion reportaba OK aunque fallase por "Permission denied" (proceso aun vivo). Ahora: (1) tras `taskkill.exe`, poll de hasta 3s sobre `tasklist.exe` esperando muerte real del proceso; (2) `cp` envuelto en retry 5 veces con backoff 0.5s y re-taskkill entre intentos; (3) si los 5 intentos fallan, `return 1` (antes: silently continued). +v1.0.0 — Initial. diff --git a/bash/functions/infra/deploy_cpp_exe_to_windows.sh b/bash/functions/infra/deploy_cpp_exe_to_windows.sh index 4d94b2cb..b0bace02 100644 --- a/bash/functions/infra/deploy_cpp_exe_to_windows.sh +++ b/bash/functions/infra/deploy_cpp_exe_to_windows.sh @@ -30,12 +30,38 @@ deploy_cpp_exe_to_windows() { mkdir -p "$dest" "$assets" # --- 3. Pre-deploy: matar proceso si esta corriendo en Windows --- + # Windows libera el file handle async tras taskkill. Hacemos poll hasta que + # el proceso desaparezca de tasklist o se agote el timeout. if command -v taskkill.exe >/dev/null 2>&1; then taskkill.exe /IM "${app}.exe" /F >/dev/null 2>&1 || true + local i + for i in 1 2 3 4 5 6 7 8 9 10; do + if ! tasklist.exe /FI "IMAGENAME eq ${app}.exe" /NH 2>/dev/null \ + | grep -qi "^${app}.exe"; then + break + fi + sleep 0.3 + done fi - # --- 4. Copiar .exe al top level --- - cp -v "$exe_src" "$dest/" + # --- 4. Copiar .exe al top level con retry --- + # Windows puede tener el archivo aun bloqueado momentaneamente; reintentar. + local cp_ok=0 + local attempt + for attempt in 1 2 3 4 5; do + if cp -v "$exe_src" "$dest/"; then + cp_ok=1 + break + fi + echo "deploy_cpp_exe_to_windows: cp intento $attempt fallo, reintentando..." >&2 + # Reintentar taskkill por si el proceso resucito o quedo zombie. + taskkill.exe /IM "${app}.exe" /F >/dev/null 2>&1 || true + sleep 0.5 + done + if [ "$cp_ok" -ne 1 ]; then + echo "ERROR: cp del .exe fallo tras 5 intentos. $exe_src -> $dest/" >&2 + return 1 + fi # --- 5. DLLs al top level (Windows DLL search convention) --- find "$build_win/apps/$app" -maxdepth 1 -type f -name '*.dll' \ diff --git a/cpp/functions/core/app_about.cpp b/cpp/functions/core/app_about.cpp index be18e6bb..018f390e 100644 --- a/cpp/functions/core/app_about.cpp +++ b/cpp/functions/core/app_about.cpp @@ -71,6 +71,8 @@ void about_window_render() { // --- Modules consumidos por la app (issue 0097) --- if (fn::app_modules_count > 0) { + ImGui::Spacing(); + ImGui::Separator(); ImGui::Spacing(); ImGui::Text("Modules (%lu)", fn::app_modules_count); if (ImGui::BeginTable("##fn_modules_table", 2, diff --git a/cpp/functions/core/app_card.cpp b/cpp/functions/core/app_card.cpp new file mode 100644 index 00000000..fbf4cf89 --- /dev/null +++ b/cpp/functions/core/app_card.cpp @@ -0,0 +1,76 @@ +#include "core/app_card.h" + +namespace fn_ui { + +static ImU32 with_alpha(ImU32 c, float a) { + ImVec4 v = ImGui::ColorConvertU32ToFloat4(c); + v.w = a; + return ImGui::ColorConvertFloat4ToU32(v); +} + +bool app_card(const AppCardData& data, ImVec2 size) { + ImGui::PushID(data.id); + ImVec2 pos = ImGui::GetCursorScreenPos(); + ImGui::InvisibleButton("##card", size); + bool hovered = ImGui::IsItemHovered(); + bool held = ImGui::IsItemActive(); + bool clicked = ImGui::IsItemClicked(); + + ImDrawList* dl = ImGui::GetWindowDrawList(); + ImVec2 p0 = pos; + ImVec2 p1 = ImVec2(pos.x + size.x, pos.y + size.y); + + ImU32 bg = with_alpha(data.accent, hovered ? 0.28f : 0.16f); + if (held) bg = with_alpha(data.accent, 0.40f); + ImU32 border = with_alpha(data.accent, hovered ? 0.95f : 0.55f); + const float rounding = 8.0f; + + dl->AddRectFilled(p0, p1, bg, rounding); + dl->AddRect(p0, p1, border, rounding, 0, 1.5f); + + const float stripe_w = 6.0f; + dl->AddRectFilled(p0, ImVec2(p0.x + stripe_w, p1.y), data.accent, rounding, + ImDrawFlags_RoundCornersLeft); + + // Clip everything past this point so wrapped text never spills out. + dl->PushClipRect(ImVec2(p0.x + stripe_w + 2.0f, p0.y + 2.0f), + ImVec2(p1.x - 2.0f, p1.y - 2.0f), true); + + const float pad_x = stripe_w + 10.0f; + const float pad_y = 10.0f; + + // Optional icon on the left + float text_left = p0.x + pad_x; + if (data.icon != (ImTextureID)0) { + float icon_size = size.y - 2.0f * pad_y; + if (icon_size > 64.0f) icon_size = 64.0f; + ImVec2 icon_p0(p0.x + pad_x, p0.y + (size.y - icon_size) * 0.5f); + ImVec2 icon_p1(icon_p0.x + icon_size, icon_p0.y + icon_size); + dl->AddImageRounded(data.icon, icon_p0, icon_p1, + ImVec2(0, 0), ImVec2(1, 1), + IM_COL32_WHITE, 6.0f); + text_left = icon_p1.x + 10.0f; + } + + ImVec2 title_pos = ImVec2(text_left, p0.y + pad_y); + ImU32 title_col = IM_COL32(245, 245, 250, 255); + if (data.title) { + dl->AddText(title_pos, title_col, data.title); + } + + if (data.description && data.description[0] != '\0') { + ImVec2 desc_pos = ImVec2(text_left, + title_pos.y + ImGui::GetTextLineHeight() + 4.0f); + ImU32 desc_col = IM_COL32(195, 200, 210, 230); + float wrap_w = (p1.x - 8.0f) - text_left; + if (wrap_w < 20.0f) wrap_w = 20.0f; + dl->AddText(NULL, 0.0f, desc_pos, desc_col, + data.description, NULL, wrap_w); + } + + dl->PopClipRect(); + ImGui::PopID(); + return clicked; +} + +} // namespace fn_ui diff --git a/cpp/functions/core/app_card.h b/cpp/functions/core/app_card.h new file mode 100644 index 00000000..12b382f0 --- /dev/null +++ b/cpp/functions/core/app_card.h @@ -0,0 +1,24 @@ +#pragma once +#include + +namespace fn_ui { + +struct AppCardData { + const char* id; // unique ImGui ID within the parent window + const char* title; // bold display name (single line) + const char* description; // optional second line; may be nullptr or "" + ImU32 accent; // accent color (IM_COL32 / hex parsed) + ImTextureID icon; // optional icon texture (0 = no icon, layout still works) +}; + +// Renders a card-shaped clickable area with: +// - rounded translucent accent background +// - solid accent stripe on the left edge +// - title on top, wrapped description below +// Uses InvisibleButton for hit-testing + ImDrawList for visuals so it does +// not inherit ImGui::Button colors. +// +// Returns true on the frame the user clicks the card. +bool app_card(const AppCardData& data, ImVec2 size); + +} // namespace fn_ui diff --git a/cpp/functions/core/app_card.md b/cpp/functions/core/app_card.md new file mode 100644 index 00000000..57e61cac --- /dev/null +++ b/cpp/functions/core/app_card.md @@ -0,0 +1,80 @@ +--- +name: app_card +kind: component +lang: cpp +domain: core +version: "1.1.0" +purity: pure +signature: "bool fn_ui::app_card(const fn_ui::AppCardData& data, ImVec2 size)" +description: "Clickable card widget with accent stripe, optional left-side icon (ImTextureID), title and wrapped description. Inner ClipRect prevents description overflow when text exceeds card height. Does NOT inherit ImGui::Button colors — uses InvisibleButton + ImDrawList so visuals are fully driven by accent." +tags: [imgui, ui, card, button, launcher, hub] +uses_functions: [] +uses_types: [] +returns: [] +returns_optional: false +error_type: "" +imports: [imgui] +tested: false +tests: [] +test_file_path: "" +file_path: "cpp/functions/core/app_card.cpp" +framework: imgui +params: + - name: data + desc: "AppCardData {id, title, description, accent}. id must be unique within the parent window. description may be nullptr or empty." + - name: size + desc: "Card size in pixels (width x height). Typical: ImVec2(280, 96)." +output: "true the frame the user clicks the card, false otherwise." +notes: "Consumed by apps/app_hub_launcher. Pattern: caller loops over a vector of cards in a grid using SameLine + Dummy for row spacing." +--- + +# app_card + +Clickable card widget for app/launcher grids. Visual identity driven by an accent color (semi-transparent fill + solid stripe + accent border) so it does NOT look like a default `ImGui::Button` (no blue). Uses `InvisibleButton` for hit-testing and `ImDrawList` for the visuals — no `ImGui::Button` is involved. + +## Ejemplo + +```cpp +#include "core/app_card.h" + +fn_ui::AppCardData card; +card.id = "graph_explorer"; +card.title = "Graph Explorer"; +card.description = "Visor de grafos GPU-accelerated"; +card.accent = IM_COL32(0x08, 0x91, 0xc2, 255); // #0891c2 + +if (fn_ui::app_card(card, ImVec2(280, 96))) { + // launch the app +} +``` + +Grid layout (N cards per row): + +```cpp +float card_w = 280.0f, card_h = 96.0f, spacing = 12.0f; +int cols = std::max(1, (int)((ImGui::GetContentRegionAvail().x + spacing) / (card_w + spacing))); +int shown = 0; +for (auto& app : apps) { + if (shown % cols != 0) ImGui::SameLine(0.0f, spacing); + fn_ui::AppCardData c{app.id.c_str(), app.title.c_str(), app.desc.c_str(), app.accent}; + if (fn_ui::app_card(c, ImVec2(card_w, card_h))) launch(app); + ++shown; + if (shown % cols == 0) ImGui::Dummy(ImVec2(0.0f, spacing - 4.0f)); +} +``` + +## Cuando usarla + +Cuando necesites un grid/lista de "cards" clicables (launchers, dashboards de modulos, selectores de proyecto) y quieras que la identidad visual venga de un accent color por card en vez de los azules por defecto de `ImGui::Button`. Si solo quieres un boton simple con texto, usa `ImGui::Button` normal. + +## Gotchas + +- `data.id` debe ser unico dentro del padre — colision = un solo card recibe el click. +- La descripcion se renderiza con wrap automatico; si `size.y` es muy pequeno el texto se sale por debajo (no clipea). Ajusta `size.y` a 90-110 px para 2-3 lineas de wrap. +- Pinta sobre `ImGui::GetWindowDrawList()` — debe llamarse dentro de una ventana ImGui activa. +- El color `data.accent` debe llevar alpha 255; las transparencias para fondo/border/hover las calcula el componente internamente. + +## Capability growth log + +v1.1.0 (2026-05-17) — Optional `icon` (ImTextureID) param renders left-side thumbnail; PushClipRect contains description overflow. +v1.0.0 (2026-05-17) — Initial. Extracted from inline rendering in `apps/app_hub_launcher/main.cpp`. diff --git a/dev/TAXONOMY.md b/dev/TAXONOMY.md new file mode 100644 index 00000000..88d29cf4 --- /dev/null +++ b/dev/TAXONOMY.md @@ -0,0 +1,96 @@ +# Taxonomia canonica — dev/issues + dev/flows + +Fuente de verdad para los campos del frontmatter YAML de issues y flows. Cualquier valor fuera de las allowlists hace fallar `fn doctor issues` y el filtrado de `dev_console`. + +## Dominios (allowlist) + +| Tag | Que entra | +|---|---| +| `meta` | telemetria, hooks, bucle reactivo, MCP, loops autonomos, taxonomia, dev_console | +| `cpp-stack` | apps C++/ImGui + primitivos GFX, GL, ImPlot, tablas, paneles, app shell | +| `kanban` | app `kanban` (features, stickers, columnas, reports, daily summary) | +| `trading` | roadmap trading (market data, broker, portfolio, backtester, journal, ...) | +| `gamedev` | roadmap gamedev (SDL3, sokol, runtime, asset pipeline, build targets) | +| `osint` | ODR + OSINT + graph_explorer | +| `data-ingest` | extractores, navegator, data_factory, dag_engine, recipes | +| `registry-quality` | auditorias, drift, registry-first refactors, uses_functions, migrations | +| `notify` | Matrix, Telegram, email, slack | +| `imagegen` | stable-diffusion, imagegen_studio, sd-cpp | +| `apps-infra` | launcher, datahub, app shell shared infra, app locations | +| `dev-ux` | fricion del agente (output mudo, paths rotos, gradle_run, slash commands) | +| `deploy` | deploy_server, systemd, VPS, rsync, webhooks | +| `frontend` | React + Vite + Mantine + hooks + visualizaciones web | +| `mcp` | MCP server, tools del registry, integracion Claude Code | +| `browser` | Chrome, CDP, navegator helpers | +| `telemetry` | call_monitor, function_stats, observability | +| `docs` | reglas, plantillas, ADRs, capability pages | + +## Tipos + +| Tag | Que es | +|---|---| +| `app` | crear app entera (apps/ o cpp/apps/) | +| `feature` | accion concreta, una rama corta | +| `bugfix` | corregir defecto | +| `refactor` | reescribir sin cambiar comportamiento | +| `chore` | auditoria, indexado, limpieza, migracion | +| `docs` | solo documentacion | +| `spike` | exploracion timeboxed | +| `epic` | roadmap con sub-issues hijo (NNNN + NNNNa, NNNNb, ...) | +| `infra` | sub-piezas de un epic | +| `planning` | issue de planificacion (no entrega codigo) | + +## Estados + +| Tag | Que significa | +|---|---| +| `pendiente` | no arrancado | +| `in-progress` | rama abierta + commits | +| `bloqueado` | espera dep no resuelta | +| `completado` | merge a master + DoD verde + archivado | +| `deferred` | fuera de scope actual, conservado | + +## Scopes + +| Tag | Que toca | +|---|---| +| `registry-only` | solo `functions/`, `types/`, `python/functions/`, etc. | +| `app-scoped` | una app concreta | +| `multi-app` | atraviesa >=2 apps | +| `cross-stack` | toca C++ + Go + Py + Frontend o equivalente | + +## Prioridades + +| Tag | Que significa | +|---|---| +| `alta` | bloquea otros items, alto impacto | +| `media` | importante pero no critico | +| `baja` | nice-to-have | + +## Flow patterns (solo dev/flows) + +| Pattern | Que es | +|---|---| +| `smoke-cron` | pipeline programado de prueba (HN, AEMET) | +| `prod-data` | caso real con datos personales/sensibles | +| `event-driven` | webhook -> fanout/notify | +| `manual-deep` | humano dispara, multi-paso interactivo | +| `gitops` | estado de servicio -> codigo versionado | +| `realtime-loop` | bucle continuo sin trigger discreto | + +## Convenciones de uso + +- `domain` es lista (multi-tag permitido). `scope`, `type`, `priority`, `status` son escalares. +- Issue sin `type` o `priority` -> warning en `fn doctor issues` + bloquea `done`. +- Issue con dominio fuera de la lista -> error en validador. +- Roadmaps usan `type: epic` con sub-issues `NNNNa`, `NNNNb`, ... que son `type: infra` o `feature`. +- Issue cerrado vive en `dev/issues/completed/` con `status: completado`. + +## Como evolucionar la taxonomia + +Anadir dominio nuevo requiere: +1. PR a este archivo + a `python/functions/pipelines/migrate_issues_frontmatter.py` (heuristica). +2. Justificacion: >=3 issues actuales o previstos que encajen. +3. Frontera neta con dominios vecinos. + +NO crear dominios para 1 issue suelto -> usa `tags:` libre. diff --git a/dev/issues/0027-cpp-gl-compute-pingpong.md b/dev/issues/0027-cpp-gl-compute-pingpong.md index d493b72f..b731d93d 100644 --- a/dev/issues/0027-cpp-gl-compute-pingpong.md +++ b/dev/issues/0027-cpp-gl-compute-pingpong.md @@ -1,3 +1,19 @@ +--- +id: "0027" +title: "C++ gl_compute_shader + gl_pingpong_fbo + DAG node Compute" +status: pendiente +type: feature +domain: + - cpp-stack +scope: multi-app +priority: alta +depends: [] +blocks: [] +related: [] +created: 2026-05-17 +updated: 2026-05-17 +tags: [] +--- # 0027 — C++ gl_compute_shader + gl_pingpong_fbo + DAG node Compute ## APP Metadata diff --git a/dev/issues/0030-cpp-audio-reactive.md b/dev/issues/0030-cpp-audio-reactive.md index 35c7149b..783c4710 100644 --- a/dev/issues/0030-cpp-audio-reactive.md +++ b/dev/issues/0030-cpp-audio-reactive.md @@ -1,3 +1,20 @@ +--- +id: "0030" +title: "C++ audio reactivo (capture + FFT + uniform feed + viz)" +status: pendiente +type: feature +domain: + - cpp-stack + - frontend +scope: multi-app +priority: media +depends: [] +blocks: [] +related: [] +created: 2026-05-17 +updated: 2026-05-17 +tags: [] +--- # 0030 — C++ audio reactivo (capture + FFT + uniform feed + viz) ## APP Metadata diff --git a/dev/issues/0033-cpp-http-ws-inspector.md b/dev/issues/0033-cpp-http-ws-inspector.md index 395c95ab..efecd4bc 100644 --- a/dev/issues/0033-cpp-http-ws-inspector.md +++ b/dev/issues/0033-cpp-http-ws-inspector.md @@ -1,3 +1,19 @@ +--- +id: "0033" +title: "C++ http_inspector + websocket_client" +status: pendiente +type: feature +domain: + - cpp-stack +scope: multi-app +priority: baja +depends: [] +blocks: [] +related: [] +created: 2026-05-17 +updated: 2026-05-17 +tags: [] +--- # 0033 — C++ http_inspector + websocket_client ## APP Metadata diff --git a/dev/issues/0035-cpp-map-tiles.md b/dev/issues/0035-cpp-map-tiles.md index f7419b1e..49a8f65e 100644 --- a/dev/issues/0035-cpp-map-tiles.md +++ b/dev/issues/0035-cpp-map-tiles.md @@ -1,3 +1,19 @@ +--- +id: "0035" +title: "C++ map_tiles (slippy map OSM)" +status: pendiente +type: feature +domain: + - cpp-stack +scope: multi-app +priority: baja +depends: [] +blocks: [] +related: [] +created: 2026-05-17 +updated: 2026-05-17 +tags: [] +--- # 0035 — C++ map_tiles (slippy map OSM) ## APP Metadata diff --git a/dev/issues/0036-cpp-image-canvas-webcam.md b/dev/issues/0036-cpp-image-canvas-webcam.md index 12e1374f..36b1953e 100644 --- a/dev/issues/0036-cpp-image-canvas-webcam.md +++ b/dev/issues/0036-cpp-image-canvas-webcam.md @@ -1,3 +1,19 @@ +--- +id: "0036" +title: "C++ image_canvas + webcam_texture" +status: pendiente +type: feature +domain: + - cpp-stack +scope: multi-app +priority: baja +depends: [] +blocks: [] +related: [] +created: 2026-05-17 +updated: 2026-05-17 +tags: [] +--- # 0036 — C++ image_canvas + webcam_texture ## APP Metadata diff --git a/dev/issues/0051-extraction-pipeline-followups.md b/dev/issues/0051-extraction-pipeline-followups.md index 4c923695..e093a286 100644 --- a/dev/issues/0051-extraction-pipeline-followups.md +++ b/dev/issues/0051-extraction-pipeline-followups.md @@ -1,3 +1,18 @@ +--- +id: "0051" +title: "Funciones pendientes del pipeline de extraccion (NER+RE+OpenIE)" +status: pendiente +type: feature +domain: [] +scope: multi-app +priority: media +depends: [] +blocks: [] +related: [] +created: 2026-05-17 +updated: 2026-05-17 +tags: [] +--- # 0051 — Funciones pendientes del pipeline de extraccion (NER+RE+OpenIE) ## APP Metadata diff --git a/dev/issues/0054-deploy-server-registry-first-refactor.md b/dev/issues/0054-deploy-server-registry-first-refactor.md index cd48fc3a..43af6c71 100644 --- a/dev/issues/0054-deploy-server-registry-first-refactor.md +++ b/dev/issues/0054-deploy-server-registry-first-refactor.md @@ -1,3 +1,20 @@ +--- +id: "0054" +title: "deploy_server: refactor registry-first (SSH/systemd/rsync/health/docker-compose)" +status: pendiente +type: refactor +domain: + - registry-quality + - deploy +scope: multi-app +priority: alta +depends: [] +blocks: [] +related: [] +created: 2026-05-17 +updated: 2026-05-17 +tags: [] +--- # 0054 — deploy_server: refactor registry-first (SSH/systemd/rsync/health/docker-compose) ## APP Metadata diff --git a/dev/issues/0055-docker-tui-registry-first-refactor.md b/dev/issues/0055-docker-tui-registry-first-refactor.md index fd6039cc..b1d4bf5d 100644 --- a/dev/issues/0055-docker-tui-registry-first-refactor.md +++ b/dev/issues/0055-docker-tui-registry-first-refactor.md @@ -1,3 +1,19 @@ +--- +id: "0055" +title: "docker_tui: refactor para usar funciones docker_* del registry" +status: pendiente +type: refactor +domain: + - registry-quality +scope: multi-app +priority: alta +depends: [] +blocks: [] +related: [] +created: 2026-05-17 +updated: 2026-05-17 +tags: [] +--- # 0055 — docker_tui: refactor para usar funciones docker_* del registry ## APP Metadata diff --git a/dev/issues/0056-audit-python-nested-imports.md b/dev/issues/0056-audit-python-nested-imports.md index 0c5cb428..bedfdb97 100644 --- a/dev/issues/0056-audit-python-nested-imports.md +++ b/dev/issues/0056-audit-python-nested-imports.md @@ -1,3 +1,19 @@ +--- +id: "0056" +title: "audit_uses_functions: detectar imports Python anidados (`from pkg.subpkg import X`)" +status: pendiente +type: chore +domain: + - registry-quality +scope: registry-only +priority: media +depends: [] +blocks: [] +related: [] +created: 2026-05-17 +updated: 2026-05-17 +tags: [] +--- # 0056 — audit_uses_functions: detectar imports Python anidados (`from pkg.subpkg import X`) ## APP Metadata diff --git a/dev/issues/0057-audit-go-symbol-naming.md b/dev/issues/0057-audit-go-symbol-naming.md index 1f191793..6f7d9b11 100644 --- a/dev/issues/0057-audit-go-symbol-naming.md +++ b/dev/issues/0057-audit-go-symbol-naming.md @@ -1,3 +1,19 @@ +--- +id: "0057" +title: "audit_uses_functions: mejorar deteccion de simbolos Go con abreviaturas" +status: pendiente +type: chore +domain: + - registry-quality +scope: registry-only +priority: baja +depends: [] +blocks: [] +related: [] +created: 2026-05-17 +updated: 2026-05-17 +tags: [] +--- # 0057 — audit_uses_functions: mejorar deteccion de simbolos Go con abreviaturas ## APP Metadata diff --git a/dev/issues/0058-kanban-uses-functions-sync.md b/dev/issues/0058-kanban-uses-functions-sync.md index 4caa3e55..bf9b486e 100644 --- a/dev/issues/0058-kanban-uses-functions-sync.md +++ b/dev/issues/0058-kanban-uses-functions-sync.md @@ -1,3 +1,20 @@ +--- +id: "0058" +title: "kanban: sync uses_functions cuando termine WIP en curso" +status: pendiente +type: docs +domain: + - kanban + - registry-quality +scope: multi-app +priority: baja +depends: [] +blocks: [] +related: [] +created: 2026-05-17 +updated: 2026-05-17 +tags: [] +--- # 0058 — kanban: sync uses_functions cuando termine WIP en curso ## APP Metadata diff --git a/dev/issues/0059-nested-app-md-tracking.md b/dev/issues/0059-nested-app-md-tracking.md index 109f2135..94da5346 100644 --- a/dev/issues/0059-nested-app-md-tracking.md +++ b/dev/issues/0059-nested-app-md-tracking.md @@ -1,3 +1,19 @@ +--- +id: "0059" +title: "Resolver doble tracking de `apps/*/app.md` (fn_registry + sub-repo)" +status: pendiente +type: infra +domain: + - registry-quality +scope: app-scoped +priority: media +depends: [] +blocks: [] +related: [] +created: 2026-05-17 +updated: 2026-05-17 +tags: [] +--- # 0059 — Resolver doble tracking de `apps/*/app.md` (fn_registry + sub-repo) ## APP Metadata diff --git a/dev/issues/0060-fn-doctor-secrets-subcommand.md b/dev/issues/0060-fn-doctor-secrets-subcommand.md index a5c43c8c..a14df57d 100644 --- a/dev/issues/0060-fn-doctor-secrets-subcommand.md +++ b/dev/issues/0060-fn-doctor-secrets-subcommand.md @@ -1,3 +1,18 @@ +--- +id: "0060" +title: "`fn doctor secrets`: scan de secrets en TODOS los repos" +status: pendiente +type: feature +domain: [] +scope: multi-app +priority: media +depends: [] +blocks: [] +related: [] +created: 2026-05-17 +updated: 2026-05-17 +tags: [] +--- # 0060 — `fn doctor secrets`: scan de secrets en TODOS los repos ## APP Metadata diff --git a/dev/issues/0061-notify-telegram-integration.md b/dev/issues/0061-notify-telegram-integration.md index 6c4cb559..de1a5d76 100644 --- a/dev/issues/0061-notify-telegram-integration.md +++ b/dev/issues/0061-notify-telegram-integration.md @@ -1,3 +1,19 @@ +--- +id: "0061" +title: "Integrar `notify_telegram` en deploy_server + bucle reactivo" +status: pendiente +type: feature +domain: + - notify +scope: multi-app +priority: media +depends: [] +blocks: [] +related: [] +created: 2026-05-17 +updated: 2026-05-17 +tags: [] +--- # 0061 — Integrar `notify_telegram` en deploy_server + bucle reactivo ## APP Metadata diff --git a/dev/issues/0063-kanban-stickers.md b/dev/issues/0063-kanban-stickers.md index fb0ac5f2..a2349d3c 100644 --- a/dev/issues/0063-kanban-stickers.md +++ b/dev/issues/0063-kanban-stickers.md @@ -1,3 +1,19 @@ +--- +id: "0063" +title: "kanban: sistema de stickers (emojis) sobre cards" +status: pendiente +type: feature +domain: + - kanban +scope: multi-app +priority: media +depends: [] +blocks: [] +related: [] +created: 2026-05-17 +updated: 2026-05-17 +tags: [] +--- # 0063 — kanban: sistema de stickers (emojis) sobre cards ## APP Metadata diff --git a/dev/issues/0065-extract-jobs-system-to-registry.md b/dev/issues/0065-extract-jobs-system-to-registry.md index c8032bfb..e77f533b 100644 --- a/dev/issues/0065-extract-jobs-system-to-registry.md +++ b/dev/issues/0065-extract-jobs-system-to-registry.md @@ -1,11 +1,22 @@ --- -id: 0065 -title: Extraer jobs system de graph_explorer al registry (jobs_pool + cache + subprocess worker) -status: pending -priority: high +id: "53" +title: "Extraer jobs system de graph_explorer al registry (jobs_pool + cache + subprocess worker)" +status: pendiente +type: feature +domain: + - registry-quality +scope: registry-only +priority: alta +depends: [] +blocks: + - "54" +related: + - "22" + - "23" + - "0028" created: 2026-05-09 -blocks: [0066] -related: [0026, 0027, 0028] +updated: 2026-05-17 +tags: [] --- ## Contexto diff --git a/dev/issues/0066-online-data-recopilation-mvp.md b/dev/issues/0066-online-data-recopilation-mvp.md index 48fe2efc..bf0b3e92 100644 --- a/dev/issues/0066-online-data-recopilation-mvp.md +++ b/dev/issues/0066-online-data-recopilation-mvp.md @@ -1,10 +1,17 @@ --- -id: 0066 -title: online_data_recopilation — odr_console MVP (lanzador GUI + 5-pasos + 1 collector) -status: pending -priority: high +id: "54" +title: "online_data_recopilation — odr_console MVP (lanzador GUI + 5-pasos + 1 collector)" +status: pendiente +type: feature +domain: [] +scope: multi-app +priority: alta +depends: [] +blocks: [] +related: [] created: 2026-05-09 -blocked_by: [0065] +updated: 2026-05-17 +tags: [] --- ## Objetivo diff --git a/dev/issues/0067-odr-osint-prereqs-roadmap.md b/dev/issues/0067-odr-osint-prereqs-roadmap.md index fff93a74..65dc38d0 100644 --- a/dev/issues/0067-odr-osint-prereqs-roadmap.md +++ b/dev/issues/0067-odr-osint-prereqs-roadmap.md @@ -1,26 +1,20 @@ --- -id: 0067 -title: Roadmap de prereqs — issues de osint_graph que odr_console necesita antes/durante MVP -status: pending -priority: high +id: "55" +title: "Roadmap de prereqs — issues de osint_graph que odr_console necesita antes/durante MVP" +status: pendiente +type: epic +domain: + - osint +scope: cross-stack +priority: alta +depends: [] +blocks: [] +related: + - "53" + - "54" created: 2026-05-09 -related: [0065, 0066] -references: [ - "projects/osint_graph/apps/graph_explorer/issues/0033-multilang-dispatcher-embedded-python.md", - "projects/osint_graph/apps/graph_explorer/issues/0033c-fn-check-vendored.md", - "projects/osint_graph/apps/graph_explorer/issues/0033d-indexer-python-runtime-fields.md", - "projects/osint_graph/apps/graph_explorer/issues/0033e-compile-skill-orchestration.md", - "projects/osint_graph/apps/graph_explorer/issues/0038-browser-launch-cdp-control.md", - "projects/osint_graph/apps/graph_explorer/issues/0039-cookie-session-manager.md", - "projects/osint_graph/apps/graph_explorer/issues/0040-multi-profile-management.md", - "projects/osint_graph/apps/graph_explorer/issues/0029-enrichers-cdp.md", - "projects/osint_graph/apps/graph_explorer/issues/0030-deep-enrich-macro.md", - "projects/osint_graph/apps/graph_explorer/issues/0021-command-palette.md", - "projects/osint_graph/apps/graph_explorer/issues/0034-port-system-enrichers-to-go.md", - "projects/osint_graph/apps/graph_explorer/issues/0014-browser-extension.md", - "projects/osint_graph/apps/graph_explorer/issues/0012-http-ingest-endpoint.md", - "projects/osint_graph/apps/graph_explorer/issues/0017-gx-cli.md" -] +updated: 2026-05-17 +tags: [] --- ## Objetivo diff --git a/dev/issues/0068-e2e-validation-loop-fn4-fn5.md b/dev/issues/0068-e2e-validation-loop-fn4-fn5.md index a0aa0a99..831ff0a0 100644 --- a/dev/issues/0068-e2e-validation-loop-fn4-fn5.md +++ b/dev/issues/0068-e2e-validation-loop-fn4-fn5.md @@ -1,11 +1,21 @@ --- -id: 0068 -title: Cerrar bucle reactivo — fn-analizador (fase 4) y fn-mejorador (fase 5) con contrato e2e_checks -status: done -closed: 2026-05-14 -priority: high +id: "0068" +title: "Cerrar bucle reactivo — fn-analizador (fase 4) y fn-mejorador (fase 5) con contrato e2e_checks" +status: completado +type: feature +domain: + - meta +scope: multi-app +priority: alta +depends: [] +blocks: [] +related: + - "22" + - "23" + - "0028" created: 2026-05-09 -related: [0026, 0027, 0028] +updated: 2026-05-17 +tags: [] --- ## Cierre 2026-05-14 diff --git a/dev/issues/0069-autonomous-agent-loop-self-iterating-tasks.md b/dev/issues/0069-autonomous-agent-loop-self-iterating-tasks.md index a06b55c4..2023e6cb 100644 --- a/dev/issues/0069-autonomous-agent-loop-self-iterating-tasks.md +++ b/dev/issues/0069-autonomous-agent-loop-self-iterating-tasks.md @@ -1,12 +1,23 @@ --- -id: 0069 -title: Bucle autonomo de subagentes — completar y mejorar tareas sin intervencion humana -status: done -closed: 2026-05-15 -priority: medium +id: "0069" +title: "Bucle autonomo de subagentes — completar y mejorar tareas sin intervencion humana" +status: completado +type: feature +domain: + - meta +scope: multi-app +priority: media +depends: + - "0068" +blocks: [] +related: + - "22" + - "23" + - "0028" + - "0085" created: 2026-05-09 -depends_on: [0068] -related: [0026, 0027, 0028, 0085] +updated: 2026-05-17 +tags: [] --- ## Cierre 2026-05-15 diff --git a/dev/issues/0070-browser-helpers-global-roadmap.md b/dev/issues/0070-browser-helpers-global-roadmap.md index fc6edc98..85320c0a 100644 --- a/dev/issues/0070-browser-helpers-global-roadmap.md +++ b/dev/issues/0070-browser-helpers-global-roadmap.md @@ -1,11 +1,18 @@ --- -id: 0070 -title: Funciones globales del registry para control de navegador (find by text, click by text, scroll, HAR, jsonld, opengraph, ...) -status: pending -priority: medium +id: "56" +title: "Funciones globales del registry para control de navegador (find by text, click by text, scroll, HAR, jsonld, opengraph, ...)" +status: pendiente +type: epic +domain: + - browser +scope: cross-stack +priority: media +depends: [] +blocks: [] +related: [] created: 2026-05-09 -related_apps: [navegator_dashboard, graph_explorer] -related_issues_app: [navegator/0001, graph_explorer/0038] +updated: 2026-05-17 +tags: [] --- ## Contexto diff --git a/dev/issues/0071-extract-reusable-cpp-panels-roadmap.md b/dev/issues/0071-extract-reusable-cpp-panels-roadmap.md index 8a2bd6b0..4d65634a 100644 --- a/dev/issues/0071-extract-reusable-cpp-panels-roadmap.md +++ b/dev/issues/0071-extract-reusable-cpp-panels-roadmap.md @@ -1,11 +1,19 @@ --- -id: 0071 -title: Extraer paneles ImGui reutilizables de las apps C++ a cpp/functions/ — roadmap -status: pending -priority: medium +id: "57" +title: "Extraer paneles ImGui reutilizables de las apps C++ a cpp/functions/ — roadmap" +status: pendiente +type: epic +domain: + - cpp-stack + - registry-quality +scope: cross-stack +priority: media +depends: [] +blocks: [] +related: [] created: 2026-05-09 -related_apps: [graph_explorer, registry_dashboard, odr_console, navegator_dashboard] -related_issues_app: [navegator/0001] +updated: 2026-05-17 +tags: [] --- ## Contexto diff --git a/dev/issues/0071a-extract-claude-chat-panel.md b/dev/issues/0071a-extract-claude-chat-panel.md index 81d102a4..471166e6 100644 --- a/dev/issues/0071a-extract-claude-chat-panel.md +++ b/dev/issues/0071a-extract-claude-chat-panel.md @@ -1,12 +1,19 @@ --- -id: 0071a -title: Extraer `claude_chat_panel` a cpp/functions/core/ (sub-issue de 0071) -status: pending +id: "0071a" +title: "Extraer `claude_chat_panel` a cpp/functions/core/ (sub-issue de 0071)" +status: pendiente +type: feature +domain: + - registry-quality +scope: registry-only priority: alta +depends: + - "0071f" +blocks: [] +related: [] created: 2026-05-10 -parent: 0071 -related_apps: [graph_explorer, navegator_dashboard] -depends_on: [0071f] +updated: 2026-05-17 +tags: [] --- ## Contexto diff --git a/dev/issues/0071b-extract-jobs-queue-panel.md b/dev/issues/0071b-extract-jobs-queue-panel.md index 9155557b..3eb61073 100644 --- a/dev/issues/0071b-extract-jobs-queue-panel.md +++ b/dev/issues/0071b-extract-jobs-queue-panel.md @@ -1,13 +1,19 @@ --- -id: 0071b -title: Extraer `jobs_queue_panel` a cpp/functions/core/ (sub-issue de 0071) -status: pending +id: "0071b" +title: "Extraer `jobs_queue_panel` a cpp/functions/core/ (sub-issue de 0071)" +status: pendiente +type: feature +domain: + - registry-quality +scope: registry-only priority: media +depends: + - "0071f" +blocks: [] +related: [] created: 2026-05-10 -parent: 0071 -related_apps: [graph_explorer, odr_console, navegator_dashboard] -related_issues: [0065] -depends_on: [0071f] +updated: 2026-05-17 +tags: [] --- ## Contexto diff --git a/dev/issues/0071f-extract-subprocess-streamer.md b/dev/issues/0071f-extract-subprocess-streamer.md index 417fe091..81b1c6d3 100644 --- a/dev/issues/0071f-extract-subprocess-streamer.md +++ b/dev/issues/0071f-extract-subprocess-streamer.md @@ -1,11 +1,18 @@ --- -id: 0071f -title: Extraer `subprocess_streamer` a cpp/functions/core/ (sub-issue de 0071) -status: pending +id: "0071f" +title: "Extraer `subprocess_streamer` a cpp/functions/core/ (sub-issue de 0071)" +status: pendiente +type: feature +domain: + - registry-quality +scope: registry-only priority: media +depends: [] +blocks: [] +related: [] created: 2026-05-10 -parent: 0071 -related_apps: [graph_explorer] +updated: 2026-05-17 +tags: [] --- ## Contexto diff --git a/dev/issues/0071g-extract-app-db-init.md b/dev/issues/0071g-extract-app-db-init.md index da0b7fc4..43a03c2a 100644 --- a/dev/issues/0071g-extract-app-db-init.md +++ b/dev/issues/0071g-extract-app-db-init.md @@ -1,11 +1,18 @@ --- -id: 0071g -title: Extraer `app_db_init` a cpp/functions/core/ (sub-issue de 0071, Tier 4) -status: pending +id: "0071g" +title: "Extraer `app_db_init` a cpp/functions/core/ (sub-issue de 0071, Tier 4)" +status: pendiente +type: feature +domain: + - registry-quality +scope: registry-only priority: media +depends: [] +blocks: [] +related: [] created: 2026-05-10 -parent: 0071 -related_apps: [graph_explorer, navegator_dashboard, kanban, deploy_server, registry_dashboard] +updated: 2026-05-17 +tags: [] --- ## Contexto diff --git a/dev/issues/0072-gamedev-stack-roadmap.md b/dev/issues/0072-gamedev-stack-roadmap.md index c6b55723..9722a6e0 100644 --- a/dev/issues/0072-gamedev-stack-roadmap.md +++ b/dev/issues/0072-gamedev-stack-roadmap.md @@ -1,11 +1,20 @@ --- -id: 0072 -title: Stack gamedev ligero multi-plataforma + crypto (roadmap) -status: pending -priority: medium +id: "58" +title: "Stack gamedev ligero multi-plataforma + crypto (roadmap)" +status: pendiente +type: epic +domain: + - gamedev +scope: cross-stack +priority: media +depends: [] +blocks: [] +related: [] created: 2026-05-10 -tags: [gamedev, roadmap] -related_issues: [0072a, 0072b, 0072c, 0072d, 0072e, 0072f, 0072g, 0072h, 0072i, 0072j, 0072k, 0072l] +updated: 2026-05-17 +tags: + - gamedev + - roadmap --- ## Contexto diff --git a/dev/issues/0072a-gamedev-smoke-sdl3-sokol-imgui.md b/dev/issues/0072a-gamedev-smoke-sdl3-sokol-imgui.md index aa3c08f6..d743ceed 100644 --- a/dev/issues/0072a-gamedev-smoke-sdl3-sokol-imgui.md +++ b/dev/issues/0072a-gamedev-smoke-sdl3-sokol-imgui.md @@ -1,12 +1,22 @@ --- -id: 0072a -title: gamedev — smoke SDL3 + sokol_gfx + ImGui (PC + WASM) -status: pending -priority: high +id: "0072a" +title: "gamedev — smoke SDL3 + sokol_gfx + ImGui (PC + WASM)" +status: pendiente +type: feature +domain: + - cpp-stack + - gamedev +scope: multi-app +priority: alta +depends: [] +blocks: [] +related: [] created: 2026-05-10 -tags: [gamedev, cpp, wasm] -parent_issue: 0072 -related_apps: [engine_smoke] +updated: 2026-05-17 +tags: + - gamedev + - cpp + - wasm --- ## Objetivo diff --git a/dev/issues/0072b-gamedev-runtime-core.md b/dev/issues/0072b-gamedev-runtime-core.md index 70c85930..abdcc5c5 100644 --- a/dev/issues/0072b-gamedev-runtime-core.md +++ b/dev/issues/0072b-gamedev-runtime-core.md @@ -1,12 +1,21 @@ --- -id: 0072b -title: gamedev — runtime nucleo (sprite batcher, audio, input, game loop) -status: pending -priority: high +id: "0072b" +title: "gamedev — runtime nucleo (sprite batcher, audio, input, game loop)" +status: pendiente +type: feature +domain: + - gamedev +scope: multi-app +priority: alta +depends: + - "0072a" +blocks: [] +related: [] created: 2026-05-10 -tags: [gamedev, cpp] -parent_issue: 0072 -depends_on: [0072a] +updated: 2026-05-17 +tags: + - gamedev + - cpp --- ## Objetivo diff --git a/dev/issues/0072c-gamedev-asset-pipeline.md b/dev/issues/0072c-gamedev-asset-pipeline.md index 4496c0a2..4dfcfacd 100644 --- a/dev/issues/0072c-gamedev-asset-pipeline.md +++ b/dev/issues/0072c-gamedev-asset-pipeline.md @@ -1,12 +1,22 @@ --- -id: 0072c -title: gamedev — asset pipeline (atlas packer, MSDF fonts, tilemap, shader translate) -status: pending -priority: high +id: "0072c" +title: "gamedev — asset pipeline (atlas packer, MSDF fonts, tilemap, shader translate)" +status: pendiente +type: feature +domain: + - gamedev +scope: multi-app +priority: alta +depends: + - "0072b" +blocks: [] +related: [] created: 2026-05-10 -tags: [gamedev, cpp, assets] -parent_issue: 0072 -depends_on: [0072b] +updated: 2026-05-17 +tags: + - gamedev + - cpp + - assets --- ## Objetivo diff --git a/dev/issues/0072d-gamedev-wasm-build-size-budget.md b/dev/issues/0072d-gamedev-wasm-build-size-budget.md index c86d21e3..93a5bde1 100644 --- a/dev/issues/0072d-gamedev-wasm-build-size-budget.md +++ b/dev/issues/0072d-gamedev-wasm-build-size-budget.md @@ -1,12 +1,23 @@ --- -id: 0072d -title: gamedev — WASM build pipeline + size budget -status: pending -priority: high +id: "0072d" +title: "gamedev — WASM build pipeline + size budget" +status: pendiente +type: feature +domain: + - gamedev +scope: multi-app +priority: alta +depends: + - "0072a" + - "0072b" +blocks: [] +related: [] created: 2026-05-10 -tags: [gamedev, wasm, infra] -parent_issue: 0072 -depends_on: [0072a, 0072b] +updated: 2026-05-17 +tags: + - gamedev + - wasm + - infra --- ## Objetivo diff --git a/dev/issues/0072e-gamedev-crypto-bridge-web3.md b/dev/issues/0072e-gamedev-crypto-bridge-web3.md index 8066e321..28a877b6 100644 --- a/dev/issues/0072e-gamedev-crypto-bridge-web3.md +++ b/dev/issues/0072e-gamedev-crypto-bridge-web3.md @@ -1,12 +1,24 @@ --- -id: 0072e -title: gamedev — bridge crypto Web3 (wallets, sign tx) via JS interop en WASM -status: pending -priority: high +id: "0072e" +title: "gamedev — bridge crypto Web3 (wallets, sign tx) via JS interop en WASM" +status: pendiente +type: feature +domain: + - gamedev +scope: multi-app +priority: alta +depends: + - "0072a" + - "0072d" +blocks: [] +related: [] created: 2026-05-10 -tags: [gamedev, wasm, crypto, web3] -parent_issue: 0072 -depends_on: [0072a, 0072d] +updated: 2026-05-17 +tags: + - gamedev + - wasm + - crypto + - web3 --- ## Objetivo diff --git a/dev/issues/0072f-gamedev-crypto-onchain-assets-payments.md b/dev/issues/0072f-gamedev-crypto-onchain-assets-payments.md index 2321beae..da34fefc 100644 --- a/dev/issues/0072f-gamedev-crypto-onchain-assets-payments.md +++ b/dev/issues/0072f-gamedev-crypto-onchain-assets-payments.md @@ -1,12 +1,23 @@ --- -id: 0072f -title: gamedev — crypto on-chain (NFT assets, payments, leaderboards firmadas) -status: pending -priority: medium +id: "0072f" +title: "gamedev — crypto on-chain (NFT assets, payments, leaderboards firmadas)" +status: pendiente +type: feature +domain: + - gamedev +scope: multi-app +priority: media +depends: + - "0072e" +blocks: [] +related: [] created: 2026-05-10 -tags: [gamedev, crypto, web3, nft] -parent_issue: 0072 -depends_on: [0072e] +updated: 2026-05-17 +tags: + - gamedev + - crypto + - web3 + - nft --- ## Objetivo diff --git a/dev/issues/0072g-gamedev-android-build.md b/dev/issues/0072g-gamedev-android-build.md index 731ba709..eb0a0345 100644 --- a/dev/issues/0072g-gamedev-android-build.md +++ b/dev/issues/0072g-gamedev-android-build.md @@ -1,12 +1,23 @@ --- -id: 0072g -title: gamedev — Android build (NDK + touch input + virtual gamepad + WalletConnect) -status: pending -priority: medium +id: "0072g" +title: "gamedev — Android build (NDK + touch input + virtual gamepad + WalletConnect)" +status: pendiente +type: feature +domain: + - gamedev +scope: multi-app +priority: media +depends: + - "0072b" + - "0072c" +blocks: [] +related: [] created: 2026-05-10 -tags: [gamedev, android, mobile] -parent_issue: 0072 -depends_on: [0072b, 0072c] +updated: 2026-05-17 +tags: + - gamedev + - android + - mobile --- ## Objetivo diff --git a/dev/issues/0072h-gamedev-ios-build.md b/dev/issues/0072h-gamedev-ios-build.md index c1e081c8..0091cbc4 100644 --- a/dev/issues/0072h-gamedev-ios-build.md +++ b/dev/issues/0072h-gamedev-ios-build.md @@ -1,12 +1,23 @@ --- -id: 0072h -title: gamedev — iOS build (Xcode + Metal via sokol + safe area + WalletConnect) -status: pending -priority: medium +id: "0072h" +title: "gamedev — iOS build (Xcode + Metal via sokol + safe area + WalletConnect)" +status: pendiente +type: feature +domain: + - gamedev +scope: multi-app +priority: media +depends: + - "0072b" + - "0072c" +blocks: [] +related: [] created: 2026-05-10 -tags: [gamedev, ios, mobile] -parent_issue: 0072 -depends_on: [0072b, 0072c] +updated: 2026-05-17 +tags: + - gamedev + - ios + - mobile --- ## Objetivo diff --git a/dev/issues/0072i-gamedev-editor-app.md b/dev/issues/0072i-gamedev-editor-app.md index b13a68d5..dd02ca40 100644 --- a/dev/issues/0072i-gamedev-editor-app.md +++ b/dev/issues/0072i-gamedev-editor-app.md @@ -1,12 +1,24 @@ --- -id: 0072i -title: gamedev — editor visual `game_editor` (scene tree, asset browser, inspector) -status: pending -priority: medium +id: "0072i" +title: "gamedev — editor visual `game_editor` (scene tree, asset browser, inspector)" +status: pendiente +type: feature +domain: + - gamedev +scope: app-scoped +priority: media +depends: + - "0072b" + - "0072c" +blocks: [] +related: [] created: 2026-05-10 -tags: [gamedev, cpp, editor, tooling] -parent_issue: 0072 -depends_on: [0072b, 0072c] +updated: 2026-05-17 +tags: + - gamedev + - cpp + - editor + - tooling --- ## Objetivo diff --git a/dev/issues/0072j-gamedev-physics-box2d.md b/dev/issues/0072j-gamedev-physics-box2d.md index 38d40e1d..74ffaa96 100644 --- a/dev/issues/0072j-gamedev-physics-box2d.md +++ b/dev/issues/0072j-gamedev-physics-box2d.md @@ -1,12 +1,22 @@ --- -id: 0072j -title: gamedev — physics 2D (Box2D integration + funciones registry) -status: pending -priority: medium +id: "0072j" +title: "gamedev — physics 2D (Box2D integration + funciones registry)" +status: pendiente +type: feature +domain: + - gamedev +scope: multi-app +priority: media +depends: + - "0072b" +blocks: [] +related: [] created: 2026-05-10 -tags: [gamedev, cpp, physics] -parent_issue: 0072 -depends_on: [0072b] +updated: 2026-05-17 +tags: + - gamedev + - cpp + - physics --- ## Objetivo diff --git a/dev/issues/0072k-gamedev-demo-platformer.md b/dev/issues/0072k-gamedev-demo-platformer.md index f5f69179..3d4cc46c 100644 --- a/dev/issues/0072k-gamedev-demo-platformer.md +++ b/dev/issues/0072k-gamedev-demo-platformer.md @@ -1,13 +1,25 @@ --- -id: 0072k -title: gamedev — demo plataformero `engine_demo` (referencia stack completo) -status: pending -priority: high +id: "0072k" +title: "gamedev — demo plataformero `engine_demo` (referencia stack completo)" +status: pendiente +type: feature +domain: + - gamedev +scope: multi-app +priority: alta +depends: + - "0072b" + - "0072c" + - "0072d" + - "0072j" +blocks: [] +related: [] created: 2026-05-10 -tags: [gamedev, cpp, demo] -parent_issue: 0072 -depends_on: [0072b, 0072c, 0072d, 0072j] -related_issues: [0072e, 0072f, 0072g, 0072h] +updated: 2026-05-17 +tags: + - gamedev + - cpp + - demo --- ## Objetivo diff --git a/dev/issues/0072l-gamedev-scripting-optional.md b/dev/issues/0072l-gamedev-scripting-optional.md index e1ece38d..5584eaf1 100644 --- a/dev/issues/0072l-gamedev-scripting-optional.md +++ b/dev/issues/0072l-gamedev-scripting-optional.md @@ -1,12 +1,22 @@ --- -id: 0072l -title: gamedev — scripting opcional (wren / lua / hot reload C++ dylib) +id: "0072l" +title: "gamedev — scripting opcional (wren / lua / hot reload C++ dylib)" status: deferred -priority: low +type: feature +domain: + - gamedev +scope: multi-app +priority: baja +depends: + - "0072k" +blocks: [] +related: [] created: 2026-05-10 -tags: [gamedev, cpp, scripting] -parent_issue: 0072 -depends_on: [0072k] +updated: 2026-05-17 +tags: + - gamedev + - cpp + - scripting --- ## Objetivo diff --git a/dev/issues/0076-gradle_run-no-detecta-android-sdk-path.md b/dev/issues/0076-gradle_run-no-detecta-android-sdk-path.md index e76b0bef..250d04c6 100644 --- a/dev/issues/0076-gradle_run-no-detecta-android-sdk-path.md +++ b/dev/issues/0076-gradle_run-no-detecta-android-sdk-path.md @@ -1,10 +1,18 @@ --- -id: 0076 -title: gradle_run no detecta SDK en $HOME/android-sdk (donde lo deja install_android_sdk) -status: pending -priority: medium +id: "62" +title: "gradle_run no detecta SDK en $HOME/android-sdk (donde lo deja install_android_sdk)" +status: pendiente +type: feature +domain: + - dev-ux +scope: multi-app +priority: media +depends: [] +blocks: [] +related: [] created: 2026-05-10 -related_functions: [gradle_run_bash_infra, install_android_sdk_bash_infra] +updated: 2026-05-17 +tags: [] --- ## Sintoma diff --git a/dev/issues/0077-fn-run-bash-output-mudo.md b/dev/issues/0077-fn-run-bash-output-mudo.md index 8c02f965..383e4b2a 100644 --- a/dev/issues/0077-fn-run-bash-output-mudo.md +++ b/dev/issues/0077-fn-run-bash-output-mudo.md @@ -1,10 +1,18 @@ --- -id: 0077 -title: fn run no propaga stdout/stderr al usuario -status: pending -priority: medium +id: "63" +title: "fn run no propaga stdout/stderr al usuario" +status: pendiente +type: feature +domain: + - dev-ux +scope: multi-app +priority: media +depends: [] +blocks: [] +related: [] created: 2026-05-10 -related_components: [cmd/fn, fn run dispatcher] +updated: 2026-05-17 +tags: [] --- ## Sintoma diff --git a/dev/issues/0082-compile-sd-cpp-binary.md b/dev/issues/0082-compile-sd-cpp-binary.md index 1cb382d4..67c506ba 100644 --- a/dev/issues/0082-compile-sd-cpp-binary.md +++ b/dev/issues/0082-compile-sd-cpp-binary.md @@ -1,11 +1,19 @@ --- -id: 0082 -title: Compilar binario `sd` (stable-diffusion.cpp) para sdcli_generate_go_ml +id: "0082" +title: "Compilar binario `sd` (stable-diffusion.cpp) para sdcli_generate_go_ml" status: pendiente -priority: media -created: 2026-05-13 type: feature -related_components: [functions/ml/sdcli_generate.go, functions/ml/sdcli_resolve_binary.go, projects/imagegen] +domain: + - cpp-stack + - imagegen +scope: multi-app +priority: media +depends: [] +blocks: [] +related: [] +created: 2026-05-13 +updated: 2026-05-17 +tags: [] --- ## Objetivo diff --git a/dev/issues/0083-imagegen-spike02-cross-validation.md b/dev/issues/0083-imagegen-spike02-cross-validation.md index 2ff0e6b9..27a48b13 100644 --- a/dev/issues/0083-imagegen-spike02-cross-validation.md +++ b/dev/issues/0083-imagegen-spike02-cross-validation.md @@ -1,11 +1,18 @@ --- -id: 0083 -title: imagegen — notebook 02 validacion cruzada diffusers vs sdcpp_python +id: "0083" +title: "imagegen — notebook 02 validacion cruzada diffusers vs sdcpp_python" status: pendiente -priority: alta -created: 2026-05-13 type: feature -related_components: [projects/imagegen/analysis/spike_diffusers_vs_sdcpp] +domain: + - imagegen +scope: multi-app +priority: alta +depends: [] +blocks: [] +related: [] +created: 2026-05-13 +updated: 2026-05-17 +tags: [] --- ## Objetivo diff --git a/dev/issues/0084-imagegen-studio-go-app.md b/dev/issues/0084-imagegen-studio-go-app.md index fd1a8314..2543b811 100644 --- a/dev/issues/0084-imagegen-studio-go-app.md +++ b/dev/issues/0084-imagegen-studio-go-app.md @@ -1,11 +1,18 @@ --- -id: 0084 -title: imagegen_studio — app Go binario producto (Fase 3 plan stack) +id: "0084" +title: "imagegen_studio — app Go binario producto (Fase 3 plan stack)" status: pendiente -priority: media -created: 2026-05-13 type: feature -related_components: [functions/ml/sdcli_*.go, functions/ml/generation_config_go_ml, projects/imagegen] +domain: + - imagegen +scope: app-scoped +priority: media +depends: [] +blocks: [] +related: [] +created: 2026-05-13 +updated: 2026-05-17 +tags: [] --- ## Objetivo diff --git a/dev/issues/0085-registry-call-standardization-and-usage-tracking.md b/dev/issues/0085-registry-call-standardization-and-usage-tracking.md index e21b7a3b..d770e174 100644 --- a/dev/issues/0085-registry-call-standardization-and-usage-tracking.md +++ b/dev/issues/0085-registry-call-standardization-and-usage-tracking.md @@ -1,11 +1,20 @@ --- -id: 0085 -title: Estandarizar llamadas a funciones del registry desde Claude + app de monitorizacion de uso -status: done -closed: 2026-05-15 -priority: high +id: "0085" +title: "Estandarizar llamadas a funciones del registry desde Claude + app de monitorizacion de uso" +status: completado +type: feature +domain: + - meta +scope: multi-app +priority: alta +depends: [] +blocks: [] +related: + - "0068" + - "0069" created: 2026-05-13 -related: [0068, 0069] +updated: 2026-05-17 +tags: [] --- ## Cierre 2026-05-15 diff --git a/dev/issues/0086-claude-md-delegation-and-capability-groups.md b/dev/issues/0086-claude-md-delegation-and-capability-groups.md index d2be2842..dbebb885 100644 --- a/dev/issues/0086-claude-md-delegation-and-capability-groups.md +++ b/dev/issues/0086-claude-md-delegation-and-capability-groups.md @@ -1,11 +1,20 @@ --- -id: 0086 -title: Refactor incremental de CLAUDE.md — delegacion agresiva a fn-constructor + capability groups por tags -status: done -closed: 2026-05-14 -priority: high +id: "0086" +title: "Refactor incremental de CLAUDE.md — delegacion agresiva a fn-constructor + capability groups por tags" +status: completado +type: feature +domain: + - meta +scope: multi-app +priority: alta +depends: [] +blocks: [] +related: + - "0069" + - "0085" created: 2026-05-13 -related: [0069, 0085] +updated: 2026-05-17 +tags: [] --- ## Cierre 2026-05-14 diff --git a/dev/issues/0087-capability-discovery-acceleration.md b/dev/issues/0087-capability-discovery-acceleration.md index df655229..b1318dd1 100644 --- a/dev/issues/0087-capability-discovery-acceleration.md +++ b/dev/issues/0087-capability-discovery-acceleration.md @@ -1,3 +1,19 @@ +--- +id: "0087" +title: "Capability Discovery Acceleration" +status: pendiente +type: feature +domain: + - meta +scope: multi-app +priority: alta +depends: [] +blocks: [] +related: [] +created: 2026-05-17 +updated: 2026-05-17 +tags: [] +--- # 0087 — Capability Discovery Acceleration **Status:** done diff --git a/dev/issues/0088-kanban-requester-empty-nav.md b/dev/issues/0088-kanban-requester-empty-nav.md index c836a53c..d0e781b2 100644 --- a/dev/issues/0088-kanban-requester-empty-nav.md +++ b/dev/issues/0088-kanban-requester-empty-nav.md @@ -1,10 +1,18 @@ --- id: "0088" title: "kanban: requester input vacío + navegación con teclado" -status: open -created_at: 2026-05-14 -priority: medium -app: kanban +status: pendiente +type: feature +domain: + - kanban +scope: multi-app +priority: media +depends: [] +blocks: [] +related: [] +created: 2026-05-17 +updated: 2026-05-17 +tags: [] --- ## Problema diff --git a/dev/issues/0088-trading-skill-management-roadmap.md b/dev/issues/0088-trading-skill-management-roadmap.md index 5aaa64dc..f93cd101 100644 --- a/dev/issues/0088-trading-skill-management-roadmap.md +++ b/dev/issues/0088-trading-skill-management-roadmap.md @@ -1,3 +1,19 @@ +--- +id: "0088" +title: "Trading & Skill Management Roadmap" +status: pendiente +type: epic +domain: + - trading +scope: cross-stack +priority: alta +depends: [] +blocks: [] +related: [] +created: 2026-05-17 +updated: 2026-05-17 +tags: [] +--- # 0088 — Trading & Skill Management Roadmap **Status:** pendiente diff --git a/dev/issues/0088a-trading-project-scaffolding.md b/dev/issues/0088a-trading-project-scaffolding.md index 68d3da42..cc5a31bc 100644 --- a/dev/issues/0088a-trading-project-scaffolding.md +++ b/dev/issues/0088a-trading-project-scaffolding.md @@ -1,3 +1,19 @@ +--- +id: "0088a" +title: "Trading: project scaffolding" +status: pendiente +type: feature +domain: + - trading +scope: multi-app +priority: alta +depends: [] +blocks: [] +related: [] +created: 2026-05-17 +updated: 2026-05-17 +tags: [] +--- # 0088a — Trading: project scaffolding **Status:** pendiente diff --git a/dev/issues/0088b-trading-market-data-capability-group.md b/dev/issues/0088b-trading-market-data-capability-group.md index 18a14c7a..e386006a 100644 --- a/dev/issues/0088b-trading-market-data-capability-group.md +++ b/dev/issues/0088b-trading-market-data-capability-group.md @@ -1,3 +1,20 @@ +--- +id: "0088b" +title: "Trading: capability group `market_data`" +status: pendiente +type: feature +domain: + - trading + - meta +scope: multi-app +priority: alta +depends: [] +blocks: [] +related: [] +created: 2026-05-17 +updated: 2026-05-17 +tags: [] +--- # 0088b — Trading: capability group `market_data` **Status:** pendiente diff --git a/dev/issues/0088c-trading-broker-interface-and-paper-adapter.md b/dev/issues/0088c-trading-broker-interface-and-paper-adapter.md index 446ebc08..cfe1609d 100644 --- a/dev/issues/0088c-trading-broker-interface-and-paper-adapter.md +++ b/dev/issues/0088c-trading-broker-interface-and-paper-adapter.md @@ -1,3 +1,19 @@ +--- +id: "0088c" +title: "Trading: broker interface + adapter paper" +status: pendiente +type: feature +domain: + - trading +scope: multi-app +priority: alta +depends: [] +blocks: [] +related: [] +created: 2026-05-17 +updated: 2026-05-17 +tags: [] +--- # 0088c — Trading: broker interface + adapter paper **Status:** pendiente diff --git a/dev/issues/0088d-trading-portfolio-tracker-app.md b/dev/issues/0088d-trading-portfolio-tracker-app.md index 029454f9..7e8e3bc7 100644 --- a/dev/issues/0088d-trading-portfolio-tracker-app.md +++ b/dev/issues/0088d-trading-portfolio-tracker-app.md @@ -1,3 +1,19 @@ +--- +id: "0088d" +title: "Trading: app `portfolio_tracker` (ledger INSERT-only)" +status: pendiente +type: feature +domain: + - trading +scope: app-scoped +priority: alta +depends: [] +blocks: [] +related: [] +created: 2026-05-17 +updated: 2026-05-17 +tags: [] +--- # 0088d — Trading: app `portfolio_tracker` (ledger INSERT-only) **Status:** pendiente diff --git a/dev/issues/0088e-trading-strategy-capability-group.md b/dev/issues/0088e-trading-strategy-capability-group.md index dcb32d3f..c06de7e5 100644 --- a/dev/issues/0088e-trading-strategy-capability-group.md +++ b/dev/issues/0088e-trading-strategy-capability-group.md @@ -1,3 +1,20 @@ +--- +id: "0088e" +title: "Trading: capability group `strategy` + Strategy contract" +status: pendiente +type: feature +domain: + - trading + - meta +scope: multi-app +priority: alta +depends: [] +blocks: [] +related: [] +created: 2026-05-17 +updated: 2026-05-17 +tags: [] +--- # 0088e — Trading: capability group `strategy` + Strategy contract **Status:** pendiente diff --git a/dev/issues/0088f-trading-risk-capability-group-and-kill-switch.md b/dev/issues/0088f-trading-risk-capability-group-and-kill-switch.md index 34f3b6b6..f5f4454b 100644 --- a/dev/issues/0088f-trading-risk-capability-group-and-kill-switch.md +++ b/dev/issues/0088f-trading-risk-capability-group-and-kill-switch.md @@ -1,3 +1,20 @@ +--- +id: "0088f" +title: "Trading: capability group `risk` + kill_switch" +status: pendiente +type: feature +domain: + - trading + - meta +scope: multi-app +priority: alta +depends: [] +blocks: [] +related: [] +created: 2026-05-17 +updated: 2026-05-17 +tags: [] +--- # 0088f — Trading: capability group `risk` + kill_switch **Status:** pendiente diff --git a/dev/issues/0088g-trading-backtester-app.md b/dev/issues/0088g-trading-backtester-app.md index 24788160..81994a47 100644 --- a/dev/issues/0088g-trading-backtester-app.md +++ b/dev/issues/0088g-trading-backtester-app.md @@ -1,3 +1,19 @@ +--- +id: "0088g" +title: "Trading: app `backtester`" +status: pendiente +type: feature +domain: + - trading +scope: app-scoped +priority: alta +depends: [] +blocks: [] +related: [] +created: 2026-05-17 +updated: 2026-05-17 +tags: [] +--- # 0088g — Trading: app `backtester` **Status:** pendiente diff --git a/dev/issues/0088h-trading-live-runner-service.md b/dev/issues/0088h-trading-live-runner-service.md index 5a8d9a03..f9d84d8d 100644 --- a/dev/issues/0088h-trading-live-runner-service.md +++ b/dev/issues/0088h-trading-live-runner-service.md @@ -1,3 +1,19 @@ +--- +id: "0088h" +title: "Trading: app `live_runner` (service, paper-first, broker real behind flag)" +status: pendiente +type: feature +domain: + - trading +scope: multi-app +priority: alta +depends: [] +blocks: [] +related: [] +created: 2026-05-17 +updated: 2026-05-17 +tags: [] +--- # 0088h — Trading: app `live_runner` (service, paper-first, broker real behind flag) **Status:** pendiente diff --git a/dev/issues/0088i-trading-journal-app.md b/dev/issues/0088i-trading-journal-app.md index 6753e8a7..7e5aec48 100644 --- a/dev/issues/0088i-trading-journal-app.md +++ b/dev/issues/0088i-trading-journal-app.md @@ -1,3 +1,19 @@ +--- +id: "0088i" +title: "Trading: app `trading_journal` (reflection log)" +status: pendiente +type: feature +domain: + - trading +scope: app-scoped +priority: alta +depends: [] +blocks: [] +related: [] +created: 2026-05-17 +updated: 2026-05-17 +tags: [] +--- # 0088i — Trading: app `trading_journal` (reflection log) **Status:** pendiente diff --git a/dev/issues/0088j-trading-reactive-loop-wiring.md b/dev/issues/0088j-trading-reactive-loop-wiring.md index bf0cbec6..4ebe1c33 100644 --- a/dev/issues/0088j-trading-reactive-loop-wiring.md +++ b/dev/issues/0088j-trading-reactive-loop-wiring.md @@ -1,3 +1,20 @@ +--- +id: "0088j" +title: "Trading: wiring del bucle reactivo (assertions + proposals)" +status: pendiente +type: feature +domain: + - trading + - frontend +scope: multi-app +priority: alta +depends: [] +blocks: [] +related: [] +created: 2026-05-17 +updated: 2026-05-17 +tags: [] +--- # 0088j — Trading: wiring del bucle reactivo (assertions + proposals) **Status:** pendiente diff --git a/dev/issues/0089-kanban-column-max-time.md b/dev/issues/0089-kanban-column-max-time.md index 002141a0..fbfef633 100644 --- a/dev/issues/0089-kanban-column-max-time.md +++ b/dev/issues/0089-kanban-column-max-time.md @@ -1,10 +1,18 @@ --- id: "0089" title: "kanban: tiempo maximo por columna con borde rojo" -status: open -created_at: 2026-05-14 -priority: medium -app: kanban +status: pendiente +type: feature +domain: + - kanban +scope: multi-app +priority: media +depends: [] +blocks: [] +related: [] +created: 2026-05-17 +updated: 2026-05-17 +tags: [] --- ## Problema diff --git a/dev/issues/0090-kanban-column-random-pick.md b/dev/issues/0090-kanban-column-random-pick.md index 975dbe7d..9cf7caa7 100644 --- a/dev/issues/0090-kanban-column-random-pick.md +++ b/dev/issues/0090-kanban-column-random-pick.md @@ -1,10 +1,18 @@ --- id: "0090" title: "kanban: Seleccionar Aleatorio en columna con animacion de ruleta" -status: open -created_at: 2026-05-14 -priority: medium -app: kanban +status: pendiente +type: feature +domain: + - kanban +scope: multi-app +priority: media +depends: [] +blocks: [] +related: [] +created: 2026-05-17 +updated: 2026-05-17 +tags: [] --- ## Problema diff --git a/dev/issues/0091-kanban-sidebar-drag-zones.md b/dev/issues/0091-kanban-sidebar-drag-zones.md index ff0e29ad..9e47ba43 100644 --- a/dev/issues/0091-kanban-sidebar-drag-zones.md +++ b/dev/issues/0091-kanban-sidebar-drag-zones.md @@ -1,10 +1,18 @@ --- id: "0091" title: "kanban: drag-aware dropzones para abrir/cerrar sidebar" -status: open -created_at: 2026-05-14 -priority: medium -app: kanban +status: pendiente +type: feature +domain: + - kanban +scope: multi-app +priority: media +depends: [] +blocks: [] +related: [] +created: 2026-05-17 +updated: 2026-05-17 +tags: [] --- ## Problema diff --git a/dev/issues/0092-kanban-done-archive.md b/dev/issues/0092-kanban-done-archive.md index 88990027..743c3317 100644 --- a/dev/issues/0092-kanban-done-archive.md +++ b/dev/issues/0092-kanban-done-archive.md @@ -1,10 +1,18 @@ --- id: "0092" title: "kanban: archivo automatico para cards en columnas Done con +30 dias" -status: open -created_at: 2026-05-14 -priority: medium -app: kanban +status: pendiente +type: feature +domain: + - kanban +scope: multi-app +priority: media +depends: [] +blocks: [] +related: [] +created: 2026-05-17 +updated: 2026-05-17 +tags: [] --- ## Problema diff --git a/dev/issues/0093-kanban-daily-report.md b/dev/issues/0093-kanban-daily-report.md index 2caee90b..2c58bf42 100644 --- a/dev/issues/0093-kanban-daily-report.md +++ b/dev/issues/0093-kanban-daily-report.md @@ -1,10 +1,18 @@ --- id: "0093" title: "kanban: reporte diario al pulsar numero del dia en el calendario" -status: open -created_at: 2026-05-14 -priority: medium -app: kanban +status: pendiente +type: feature +domain: + - kanban +scope: multi-app +priority: media +depends: [] +blocks: [] +related: [] +created: 2026-05-17 +updated: 2026-05-17 +tags: [] --- ## Problema diff --git a/dev/issues/0094-kanban-daily-summary-pdf.md b/dev/issues/0094-kanban-daily-summary-pdf.md index 6ebe8b7f..e46c99ea 100644 --- a/dev/issues/0094-kanban-daily-summary-pdf.md +++ b/dev/issues/0094-kanban-daily-summary-pdf.md @@ -1,10 +1,18 @@ --- id: "0094" title: "kanban: bocadillo del agente + PDF descargable en reporte diario" -status: open -created_at: 2026-05-14 -priority: medium -app: kanban +status: pendiente +type: feature +domain: + - kanban +scope: multi-app +priority: media +depends: [] +blocks: [] +related: [] +created: 2026-05-17 +updated: 2026-05-17 +tags: [] --- ## Problema diff --git a/dev/issues/0095-dag-engine-cpp-imgui-frontend.md b/dev/issues/0095-dag-engine-cpp-imgui-frontend.md index 1f8f8c13..691384cf 100644 --- a/dev/issues/0095-dag-engine-cpp-imgui-frontend.md +++ b/dev/issues/0095-dag-engine-cpp-imgui-frontend.md @@ -1,3 +1,20 @@ +--- +id: "0095" +title: "Frontend C++ ImGui para `dag_engine`" +status: pendiente +type: feature +domain: + - cpp-stack + - frontend +scope: multi-app +priority: alta +depends: [] +blocks: [] +related: [] +created: 2026-05-17 +updated: 2026-05-17 +tags: [] +--- # 0095 — Frontend C++ ImGui para `dag_engine` **Status:** pendiente diff --git a/dev/issues/0096-standardize-app-locations.md b/dev/issues/0096-standardize-app-locations.md index b889abef..22c15c19 100644 --- a/dev/issues/0096-standardize-app-locations.md +++ b/dev/issues/0096-standardize-app-locations.md @@ -1,3 +1,19 @@ +--- +id: "0096" +title: "Estandarizar ubicacion de apps: fuera de carpetas por lenguaje" +status: pendiente +type: feature +domain: + - apps-infra +scope: app-scoped +priority: alta +depends: [] +blocks: [] +related: [] +created: 2026-05-17 +updated: 2026-05-17 +tags: [] +--- # 0096 — Estandarizar ubicacion de apps: fuera de carpetas por lenguaje **Status:** pendiente diff --git a/dev/issues/0097-data-factory-app.md b/dev/issues/0097-data-factory-app.md index f2e71c8f..91fa12b5 100644 --- a/dev/issues/0097-data-factory-app.md +++ b/dev/issues/0097-data-factory-app.md @@ -1,3 +1,19 @@ +--- +id: "0097" +title: "data_factory app (Factorio-style data pipeline)" +status: pendiente +type: feature +domain: + - data-ingest +scope: app-scoped +priority: alta +depends: [] +blocks: [] +related: [] +created: 2026-05-17 +updated: 2026-05-17 +tags: [] +--- # 0097 — data_factory app (Factorio-style data pipeline) **Status:** pendiente diff --git a/dev/issues/0098-navegator-extractions-enhancement.md b/dev/issues/0098-navegator-extractions-enhancement.md index cec17838..29b63c1b 100644 --- a/dev/issues/0098-navegator-extractions-enhancement.md +++ b/dev/issues/0098-navegator-extractions-enhancement.md @@ -1,3 +1,19 @@ +--- +id: "0098" +title: "Navegator extractions enhancement (Pick + Network rows + AutoExtract + data_factory bridge)" +status: pendiente +type: feature +domain: + - data-ingest +scope: multi-app +priority: alta +depends: [] +blocks: [] +related: [] +created: 2026-05-17 +updated: 2026-05-17 +tags: [] +--- # 0098 — Navegator extractions enhancement (Pick + Network rows + AutoExtract + data_factory bridge) **Status:** pendiente diff --git a/dev/issues/0099-datahub-app-launcher.md b/dev/issues/0099-datahub-app-launcher.md index f3d37d41..29bae1ed 100644 --- a/dev/issues/0099-datahub-app-launcher.md +++ b/dev/issues/0099-datahub-app-launcher.md @@ -1,3 +1,19 @@ +--- +id: "0099" +title: "datahub app (launcher central para todas las apps)" +status: pendiente +type: feature +domain: + - apps-infra +scope: app-scoped +priority: alta +depends: [] +blocks: [] +related: [] +created: 2026-05-17 +updated: 2026-05-17 +tags: [] +--- # 0099 — datahub app (launcher central para todas las apps) **Status:** pendiente diff --git a/dev/issues/0100-issues-frontmatter-migration.md b/dev/issues/0100-issues-frontmatter-migration.md index 156b4b17..7daada4f 100644 --- a/dev/issues/0100-issues-frontmatter-migration.md +++ b/dev/issues/0100-issues-frontmatter-migration.md @@ -1,3 +1,19 @@ +--- +id: "0100" +title: "Migrar frontmatter inline a YAML canonico en dev/issues/" +status: pendiente +type: chore +domain: + - registry-quality +scope: registry-only +priority: alta +depends: [] +blocks: [] +related: [] +created: 2026-05-17 +updated: 2026-05-17 +tags: [] +--- # 0100 — Migrar frontmatter inline a YAML canonico en dev/issues/ **Status:** pendiente diff --git a/dev/issues/0101-dev-console-binary.md b/dev/issues/0101-dev-console-binary.md index 07361302..5c8126f4 100644 --- a/dev/issues/0101-dev-console-binary.md +++ b/dev/issues/0101-dev-console-binary.md @@ -1,3 +1,19 @@ +--- +id: "0101" +title: "dev_console Go binario: /issue /flow /work unificados" +status: pendiente +type: app +domain: + - meta +scope: registry-only +priority: alta +depends: [] +blocks: [] +related: [] +created: 2026-05-17 +updated: 2026-05-17 +tags: [] +--- # 0101 — dev_console Go binario: /issue /flow /work unificados **Status:** pendiente diff --git a/dev/issues/0102-work-dashboard-tab.md b/dev/issues/0102-work-dashboard-tab.md index 7618cdec..37651faa 100644 --- a/dev/issues/0102-work-dashboard-tab.md +++ b/dev/issues/0102-work-dashboard-tab.md @@ -1,3 +1,19 @@ +--- +id: "0102" +title: "Tab Work en registry_dashboard (issues + flows + telemetria)" +status: pendiente +type: feature +domain: + - meta +scope: app-scoped +priority: media +depends: [] +blocks: [] +related: [] +created: 2026-05-17 +updated: 2026-05-17 +tags: [] +--- # 0102 — Tab Work en registry_dashboard (issues + flows + telemetria) **Status:** pendiente diff --git a/dev/issues/0103-taxonomy-and-slash-commands.md b/dev/issues/0103-taxonomy-and-slash-commands.md index 9f432e23..3f871235 100644 --- a/dev/issues/0103-taxonomy-and-slash-commands.md +++ b/dev/issues/0103-taxonomy-and-slash-commands.md @@ -1,3 +1,19 @@ +--- +id: "0103" +title: "Taxonomia + slash commands /issue /flow /work" +status: pendiente +type: feature +domain: + - meta +scope: registry-only +priority: alta +depends: [] +blocks: [] +related: [] +created: 2026-05-17 +updated: 2026-05-17 +tags: [] +--- # 0103 — Taxonomia + slash commands /issue /flow /work **Status:** pendiente diff --git a/dev/issues/0104-fix-issue-type-aware-dispatch.md b/dev/issues/0104-fix-issue-type-aware-dispatch.md new file mode 100644 index 00000000..823f6a43 --- /dev/null +++ b/dev/issues/0104-fix-issue-type-aware-dispatch.md @@ -0,0 +1,168 @@ +--- +id: "0104" +title: "/fix-issue type-aware dispatch (chore vs feature vs bugfix vs epic)" +status: pendiente +type: feature +domain: + - meta + - dev-ux +scope: registry-only +priority: alta +depends: + - "0100" +blocks: [] +related: + - "0101" + - "0103" +created: 2026-05-17 +updated: 2026-05-17 +tags: [slash-command, dispatch, type-aware] +--- + +# 0104 — `/fix-issue` type-aware dispatch + +## Problema + +Hoy `/fix-issue NNNN` arranca con el mismo flujo para CUALQUIER tipo de issue. Pero un `chore` (limpieza, migracion idempotente) no requiere el mismo ceremonial que un `feature` (TBD rama + acceptance + DoD), ni que un `bugfix` (reproduce + test que falla + fix + test verde), ni que un `epic` (planificacion de sub-issues, no codigo directo). + +Resultado: +- `chore` se ejecuta con TBD branch innecesaria, ralentiza. +- `bugfix` se cierra sin test de regresion porque el flujo no lo exige. +- `epic` arranca con `/git-branch` aunque no toca codigo aun (deberia abrir sub-issues primero). +- `spike` se trata como feature, sin timebox. +- `docs` requiere ramas TBD que sobran (push directo a master segun apps_tbd.md para registry). + +## Objetivo + +`/fix-issue NNNN` lee el `type:` del frontmatter (issue 0100) y aplica el playbook correspondiente. Sin type valido -> error "type missing, run `/issue tag NNNN +type:` first". + +## Dispatch por type + +### `bugfix` + +1. `/git-branch issue/NNNN-`. +2. **Reproducir el bug**: pedir al usuario pasos exactos + snippet. Si no se reproduce -> abort. +3. **Escribir test que falla** ANTES del fix. Commit `test: reproduce `. +4. Implementar fix. +5. Test verde + run suite completa de la app afectada. +6. Commit `fix: `. +7. `/git-push` (merge --no-ff master). +8. Move a `completed/`. + +### `feature` + +1. `/git-branch issue/NNNN-`. +2. **Plan corto** (2-3 frases) sobre approach + DoD a marcar. +3. Implementar bloque por bloque, commits atomicos. +4. Acceptance checkboxes verdes via tests + manual user-test. +5. Si DoD pide `User-facing`: el flow asociado debe abrir la superficie usuario. +6. `/git-push`. +7. Move a `completed/`. + +### `chore` + +1. **NO TBD branch** (push directo a master). Si toca app -> usar TBD. +2. Si es pipeline idempotente: run `--dry-run` primero, mostrar diff, run real. +3. Backup antes de toda escritura masiva (ver 0100). +4. Commit `chore: `. +5. `/full-git-push`. +6. Move a `completed/`. + +### `refactor` + +1. `/git-branch issue/NNNN-`. +2. **Sin tests verdes pre-existentes -> abort**. Refactor sin red de seguridad es feature, no refactor. +3. Aplicar **Branch by Abstraction** (ver feature_flags.md) si cambio grande. +4. Tests siguen verdes en cada commit. +5. `/git-push`. + +### `chore` + `audit` + +1. Read-only fase exploratoria. +2. Output reporte (no escribir). +3. Si el reporte requiere fix -> abrir nuevo issue `bugfix` o `chore` por hallazgo. +4. Close audit issue con reporte adjunto en `## Notas`. + +### `epic` + +1. **NO codigo directo**. Epic es planning. +2. Listar sub-issues hijo (`NNNNa`, `NNNNb`, ...) — crearlos si no existen via `/issue create`. +3. Decidir orden de ejecucion (dependencias). +4. Status del epic = `bloqueado` mientras haya hijos abiertos. +5. Cerrar solo cuando todos los hijos esten `completado`. + +### `spike` + +1. `/git-branch spike/NNNN-` (no `issue/`). +2. **Timebox declarado** en frontmatter (`tags: [timebox-2h]`). +3. Output: aprendizaje en `## Notas` + nuevo issue concreto (feature/refactor) si vale la pena seguir. +4. NO commit a master. Si el spike falla -> branch deletada, issue `deferred`. + +### `docs` + +1. NO TBD (push directo). +2. Editar `.md` o `docs/` o reglas. +3. Si toca `.claude/rules/INDEX.md` -> verificar referencias rotas. +4. Commit `docs: `. + +### `infra` + +1. Sub-issue de un epic. `/fix-issue` redirige a guidance del epic padre. +2. Aplicar dispatch del type del padre (feature/refactor habitualmente). + +### `planning` + +1. NO codigo. Similar a `epic` pero scope mas pequeño (ej. propuesta de taxonomia, ADR). +2. Output: `.md` con conclusiones. + +## Implementacion + +Slash command `.claude/commands/fix-issue.md` actualizado: + +```yaml +--- +description: "Fix issue con dispatch por type (bugfix/feature/chore/refactor/epic/spike/docs/infra/planning)" +allowed-tools: [Bash, Read, Edit, Write, Glob, Grep, Agent] +--- + +# /fix-issue NNNN + +1. Lee `dev/issues/NNNN-*.md` (parsea frontmatter YAML). +2. Lee `type:` del frontmatter. +3. Despacha al playbook correspondiente (ver dev/issues/0104-*.md). +4. Si type missing/invalido -> error con sugerencia. +``` + +Playbooks se materializan como sub-archivos en `dev/playbooks/.md` (lectura on-demand). Cada uno con steps numerados + checklist DoD. + +## Acceptance + +- [ ] `.claude/commands/fix-issue.md` lee `type:` y dispacha. +- [ ] `dev/playbooks/{bugfix,feature,chore,refactor,epic,spike,docs,infra,planning}.md` existen. +- [ ] `/fix-issue NNNN` sin `type:` valido -> error claro + sugerencia. +- [ ] Documentacion en `.claude/rules/` referencia los playbooks. +- [ ] Smoke test: `/fix-issue 0099` (type=app) elige el playbook adecuado (mapea app -> feature playbook por defecto). + +## Definition of Done + +### Generico + +- [ ] **Repetibilidad**: misma issue type produce mismo playbook 100x. +- [ ] **Observabilidad**: log "dispatch: type=feature" antes de arrancar. +- [ ] **Error-path**: type invalido -> error con sugerencia "did you mean ...?". +- [ ] **Idempotencia**: si la rama ya existe, reanudar (no abortar). +- [ ] **Secrets**: N/A. +- [ ] **Docs**: cada playbook tiene ejemplo + gotchas. +- [ ] **Registry-first**: playbooks reusan funciones del registry (git_branch, run_tests, etc.). +- [ ] **INDEX + status**: issue cerrado. + +### User-facing + +- [ ] **User-facing**: usuario teclea `/fix-issue 0099` y ve el playbook elegido como primera linea: `[dispatch] type=app -> playbook=feature (TBD branch + acceptance + DoD)`. +- [ ] **User-facing repeat**: cada issue futuro entra al playbook correcto automatico, sin que el usuario tenga que pensar. +- [ ] **User-facing onboarding**: parrafo en `dev/playbooks/README.md` explica que es cada playbook. +- [ ] **User-facing latencia**: dispatch decision <100ms. + +## Notas + +(rellenas tras correr) diff --git a/dev/issues/README.md b/dev/issues/README.md index 3af17f43..186b4aac 100644 --- a/dev/issues/README.md +++ b/dev/issues/README.md @@ -1,5 +1,12 @@ # Issues +> **Frontmatter YAML** es la fuente de verdad desde 2026-05-17 (issue 0100). +> Cada `.md` empieza con bloque `---` con `id`, `title`, `status`, `type`, `domain`, `scope`, `priority`, `depends`, `blocks`, `related`, `created`, `updated`, `tags`. +> Para listar/filtrar: `/issue list --domain trading --status pendiente` (cuando `dev_console` exista — issue 0101). +> +> Dominios canonicos: `meta cpp-stack kanban trading gamedev osint data-ingest registry-quality notify imagegen apps-infra dev-ux deploy frontend mcp browser telemetry docs`. +> La tabla debajo es vista historica (legacy) y NO se actualiza; sera sustituida por output auto-generado en issue 0102. + | ID | Título | Estado | Prioridad | Tipo | Bloquea | |----|--------|--------|-----------|------|---------| | 0001 | Jupyter create notebook | completado | — | feature | — | diff --git a/dev/issues/completed/0007a-dag-core.md b/dev/issues/completed/0007a-dag-core.md index cc2981f1..18d24148 100644 --- a/dev/issues/completed/0007a-dag-core.md +++ b/dev/issues/completed/0007a-dag-core.md @@ -1,3 +1,18 @@ +--- +id: "0007a" +title: "Funciones core del DAG engine" +status: completado +type: feature +domain: [] +scope: multi-app +priority: alta +depends: [] +blocks: [] +related: [] +created: 2026-05-17 +updated: 2026-05-17 +tags: [] +--- # 0007a — Funciones core del DAG engine ## Metadata diff --git a/dev/issues/completed/0007b-process-manager.md b/dev/issues/completed/0007b-process-manager.md index 18a25028..e23112b9 100644 --- a/dev/issues/completed/0007b-process-manager.md +++ b/dev/issues/completed/0007b-process-manager.md @@ -1,3 +1,18 @@ +--- +id: "0007b" +title: "Process manager: spawn, wait, kill, status" +status: completado +type: feature +domain: [] +scope: multi-app +priority: alta +depends: [] +blocks: [] +related: [] +created: 2026-05-17 +updated: 2026-05-17 +tags: [] +--- # 0007b — Process manager: spawn, wait, kill, status ## Metadata diff --git a/dev/issues/completed/0007c-execution-store.md b/dev/issues/completed/0007c-execution-store.md index 66a7fb0e..ef90f85a 100644 --- a/dev/issues/completed/0007c-execution-store.md +++ b/dev/issues/completed/0007c-execution-store.md @@ -1,3 +1,18 @@ +--- +id: "0007c" +title: "Execution store: persistencia de estado" +status: completado +type: feature +domain: [] +scope: multi-app +priority: alta +depends: [] +blocks: [] +related: [] +created: 2026-05-17 +updated: 2026-05-17 +tags: [] +--- # 0007c — Execution store: persistencia de estado ## Metadata diff --git a/dev/issues/completed/0007d-scheduler.md b/dev/issues/completed/0007d-scheduler.md index 4025cf87..084f9fbb 100644 --- a/dev/issues/completed/0007d-scheduler.md +++ b/dev/issues/completed/0007d-scheduler.md @@ -1,3 +1,18 @@ +--- +id: "0007d" +title: "Scheduler: cron parser y ticker" +status: completado +type: feature +domain: [] +scope: multi-app +priority: media +depends: [] +blocks: [] +related: [] +created: 2026-05-17 +updated: 2026-05-17 +tags: [] +--- # 0007d — Scheduler: cron parser y ticker ## Metadata diff --git a/dev/issues/completed/0007e-dag-executor-app.md b/dev/issues/completed/0007e-dag-executor-app.md index e01db05a..69a38c3a 100644 --- a/dev/issues/completed/0007e-dag-executor-app.md +++ b/dev/issues/completed/0007e-dag-executor-app.md @@ -1,3 +1,18 @@ +--- +id: "0007e" +title: "DAG executor app: CLI/TUI que reemplaza Dagu" +status: completado +type: feature +domain: [] +scope: app-scoped +priority: alta +depends: [] +blocks: [] +related: [] +created: 2026-05-17 +updated: 2026-05-17 +tags: [] +--- # 0007e — DAG executor app: CLI/TUI que reemplaza Dagu ## Metadata diff --git a/dev/issues/completed/0008-sqlite-api-web.md b/dev/issues/completed/0008-sqlite-api-web.md index 4445a966..64c2bfa1 100644 --- a/dev/issues/completed/0008-sqlite-api-web.md +++ b/dev/issues/completed/0008-sqlite-api-web.md @@ -1,3 +1,18 @@ +--- +id: "0008" +title: "SQLite API Web" +status: completado +type: feature +domain: [] +scope: multi-app +priority: alta +depends: [] +blocks: [] +related: [] +created: 2026-05-17 +updated: 2026-05-17 +tags: [] +--- # 0008 — SQLite API Web ## Metadata diff --git a/dev/issues/completed/0009-http-server.md b/dev/issues/completed/0009-http-server.md index 714a390e..2523d13e 100644 --- a/dev/issues/completed/0009-http-server.md +++ b/dev/issues/completed/0009-http-server.md @@ -1,3 +1,18 @@ +--- +id: "0009" +title: "HTTP Server Foundation" +status: completado +type: feature +domain: [] +scope: multi-app +priority: alta +depends: [] +blocks: [] +related: [] +created: 2026-05-17 +updated: 2026-05-17 +tags: [] +--- # 0009 — HTTP Server Foundation ## Metadata diff --git a/dev/issues/completed/0010-auth-system.md b/dev/issues/completed/0010-auth-system.md index 13de63fa..6dd4cecb 100644 --- a/dev/issues/completed/0010-auth-system.md +++ b/dev/issues/completed/0010-auth-system.md @@ -1,3 +1,18 @@ +--- +id: "0010" +title: "Auth System" +status: completado +type: feature +domain: [] +scope: multi-app +priority: alta +depends: [] +blocks: [] +related: [] +created: 2026-05-17 +updated: 2026-05-17 +tags: [] +--- # 0010 — Auth System ## Metadata diff --git a/dev/issues/completed/0011-websocket-sse.md b/dev/issues/completed/0011-websocket-sse.md index 002f540b..c9152f6a 100644 --- a/dev/issues/completed/0011-websocket-sse.md +++ b/dev/issues/completed/0011-websocket-sse.md @@ -1,3 +1,18 @@ +--- +id: "0011" +title: "WebSocket & SSE Server" +status: completado +type: feature +domain: [] +scope: multi-app +priority: alta +depends: [] +blocks: [] +related: [] +created: 2026-05-17 +updated: 2026-05-17 +tags: [] +--- # 0011 — WebSocket & SSE Server ## Metadata diff --git a/dev/issues/completed/0012-email-smtp.md b/dev/issues/completed/0012-email-smtp.md index 712b2346..9e60d49f 100644 --- a/dev/issues/completed/0012-email-smtp.md +++ b/dev/issues/completed/0012-email-smtp.md @@ -1,3 +1,18 @@ +--- +id: "0012" +title: "Email & SMTP" +status: completado +type: feature +domain: [] +scope: multi-app +priority: media +depends: [] +blocks: [] +related: [] +created: 2026-05-17 +updated: 2026-05-17 +tags: [] +--- # 0012 — Email & SMTP ## Metadata diff --git a/dev/issues/completed/0013-background-jobs.md b/dev/issues/completed/0013-background-jobs.md index 7c9f9d9f..d2ae3a6f 100644 --- a/dev/issues/completed/0013-background-jobs.md +++ b/dev/issues/completed/0013-background-jobs.md @@ -1,3 +1,18 @@ +--- +id: "0013" +title: "Background Job Queue" +status: completado +type: feature +domain: [] +scope: multi-app +priority: alta +depends: [] +blocks: [] +related: [] +created: 2026-05-17 +updated: 2026-05-17 +tags: [] +--- # 0013 — Background Job Queue ## Metadata diff --git a/dev/issues/completed/0014-file-upload.md b/dev/issues/completed/0014-file-upload.md index bf5994b9..2f23847f 100644 --- a/dev/issues/completed/0014-file-upload.md +++ b/dev/issues/completed/0014-file-upload.md @@ -1,3 +1,18 @@ +--- +id: "0014" +title: "File Upload & Storage" +status: completado +type: feature +domain: [] +scope: multi-app +priority: media +depends: [] +blocks: [] +related: [] +created: 2026-05-17 +updated: 2026-05-17 +tags: [] +--- # 0014 — File Upload & Storage ## Metadata diff --git a/dev/issues/completed/0015-db-migrations.md b/dev/issues/completed/0015-db-migrations.md index ac88f4c5..c42d532a 100644 --- a/dev/issues/completed/0015-db-migrations.md +++ b/dev/issues/completed/0015-db-migrations.md @@ -1,3 +1,18 @@ +--- +id: "0015" +title: "Database Migrations" +status: completado +type: feature +domain: [] +scope: multi-app +priority: media +depends: [] +blocks: [] +related: [] +created: 2026-05-17 +updated: 2026-05-17 +tags: [] +--- # 0015 — Database Migrations ## Metadata diff --git a/dev/issues/completed/0016-rate-limiting.md b/dev/issues/completed/0016-rate-limiting.md index 24833b6a..310ed3a4 100644 --- a/dev/issues/completed/0016-rate-limiting.md +++ b/dev/issues/completed/0016-rate-limiting.md @@ -1,3 +1,18 @@ +--- +id: "0016" +title: "Rate Limiting" +status: completado +type: feature +domain: [] +scope: multi-app +priority: media +depends: [] +blocks: [] +related: [] +created: 2026-05-17 +updated: 2026-05-17 +tags: [] +--- # 0016 — Rate Limiting ## Metadata diff --git a/dev/issues/completed/0017-frontend-hooks.md b/dev/issues/completed/0017-frontend-hooks.md index 3b0b89c7..13f12828 100644 --- a/dev/issues/completed/0017-frontend-hooks.md +++ b/dev/issues/completed/0017-frontend-hooks.md @@ -1,3 +1,19 @@ +--- +id: "0017" +title: "Frontend Data Hooks" +status: completado +type: feature +domain: + - frontend +scope: multi-app +priority: alta +depends: [] +blocks: [] +related: [] +created: 2026-05-17 +updated: 2026-05-17 +tags: [] +--- # 0017 — Frontend Data Hooks ## Metadata diff --git a/dev/issues/completed/0018-config-env.md b/dev/issues/completed/0018-config-env.md index 7fecdbd8..9ed03e11 100644 --- a/dev/issues/completed/0018-config-env.md +++ b/dev/issues/completed/0018-config-env.md @@ -1,3 +1,18 @@ +--- +id: "0018" +title: "Config & Env Management" +status: completado +type: feature +domain: [] +scope: multi-app +priority: media +depends: [] +blocks: [] +related: [] +created: 2026-05-17 +updated: 2026-05-17 +tags: [] +--- # 0018 — Config & Env Management ## Metadata diff --git a/dev/issues/completed/0019-structured-logging.md b/dev/issues/completed/0019-structured-logging.md index 21fa8c1a..610c08bb 100644 --- a/dev/issues/completed/0019-structured-logging.md +++ b/dev/issues/completed/0019-structured-logging.md @@ -1,3 +1,18 @@ +--- +id: "0019" +title: "Structured Logging Go" +status: completado +type: feature +domain: [] +scope: multi-app +priority: media +depends: [] +blocks: [] +related: [] +created: 2026-05-17 +updated: 2026-05-17 +tags: [] +--- # 0019 — Structured Logging Go ## Metadata diff --git a/dev/issues/completed/001_jupyter_create_notebook.md b/dev/issues/completed/001_jupyter_create_notebook.md index bb7ee202..4ea280bb 100644 --- a/dev/issues/completed/001_jupyter_create_notebook.md +++ b/dev/issues/completed/001_jupyter_create_notebook.md @@ -1,3 +1,18 @@ +--- +id: "001_jupyter_create_notebook" +title: "jupyter_write: crear notebooks nuevos" +status: completado +type: feature +domain: [] +scope: multi-app +priority: media +depends: [] +blocks: [] +related: [] +created: 2026-05-17 +updated: 2026-05-17 +tags: [] +--- # jupyter_write: crear notebooks nuevos **Componente:** `python/functions/notebook/jupyter_write.py` diff --git a/dev/issues/completed/0020-pdf-generation.md b/dev/issues/completed/0020-pdf-generation.md index 1ade0637..c8d9ae1a 100644 --- a/dev/issues/completed/0020-pdf-generation.md +++ b/dev/issues/completed/0020-pdf-generation.md @@ -1,3 +1,18 @@ +--- +id: "0020" +title: "PDF Generation" +status: completado +type: feature +domain: [] +scope: multi-app +priority: media +depends: [] +blocks: [] +related: [] +created: 2026-05-17 +updated: 2026-05-17 +tags: [] +--- # 0020 — PDF Generation ## Metadata diff --git a/dev/issues/completed/0021-crud-generator.md b/dev/issues/completed/0021-crud-generator.md index 9c80508b..217d270a 100644 --- a/dev/issues/completed/0021-crud-generator.md +++ b/dev/issues/completed/0021-crud-generator.md @@ -1,3 +1,18 @@ +--- +id: "0021" +title: "CRUD Generator" +status: completado +type: feature +domain: [] +scope: multi-app +priority: media +depends: [] +blocks: [] +related: [] +created: 2026-05-17 +updated: 2026-05-17 +tags: [] +--- # 0021 — CRUD Generator ## Metadata diff --git a/dev/issues/completed/0022-init-pipelines.md b/dev/issues/completed/0022-init-pipelines.md index 2a91f885..fd585964 100644 --- a/dev/issues/completed/0022-init-pipelines.md +++ b/dev/issues/completed/0022-init-pipelines.md @@ -1,3 +1,18 @@ +--- +id: "0022" +title: "Init Pipelines" +status: completado +type: feature +domain: [] +scope: multi-app +priority: alta +depends: [] +blocks: [] +related: [] +created: 2026-05-17 +updated: 2026-05-17 +tags: [] +--- # 0022 — Init Pipelines ## Metadata diff --git a/dev/issues/completed/0023-testing-utils.md b/dev/issues/completed/0023-testing-utils.md index b2a0d090..dc100e70 100644 --- a/dev/issues/completed/0023-testing-utils.md +++ b/dev/issues/completed/0023-testing-utils.md @@ -1,3 +1,18 @@ +--- +id: "0023" +title: "Testing Utilities" +status: completado +type: feature +domain: [] +scope: multi-app +priority: media +depends: [] +blocks: [] +related: [] +created: 2026-05-17 +updated: 2026-05-17 +tags: [] +--- # 0023 — Testing Utilities ## Metadata diff --git a/dev/issues/completed/0024-dashboard-yaml-split-por-tab.md b/dev/issues/completed/0024-dashboard-yaml-split-por-tab.md index bc4d93af..c2c9ad99 100644 --- a/dev/issues/completed/0024-dashboard-yaml-split-por-tab.md +++ b/dev/issues/completed/0024-dashboard-yaml-split-por-tab.md @@ -1,3 +1,18 @@ +--- +id: "0024" +title: "Split dashboard YAMLs por tab" +status: completado +type: feature +domain: [] +scope: multi-app +priority: alta +depends: [] +blocks: [] +related: [] +created: 2026-05-17 +updated: 2026-05-17 +tags: [] +--- # 0024 — Split dashboard YAMLs por tab ## APP Metadata diff --git a/dev/issues/completed/0025-cpp-text-editor-file-watcher.md b/dev/issues/completed/0025-cpp-text-editor-file-watcher.md index 8a04d276..3e814183 100644 --- a/dev/issues/completed/0025-cpp-text-editor-file-watcher.md +++ b/dev/issues/completed/0025-cpp-text-editor-file-watcher.md @@ -1,3 +1,19 @@ +--- +id: "0025" +title: "C++ text_editor + file_watcher" +status: completado +type: feature +domain: + - cpp-stack +scope: multi-app +priority: alta +depends: [] +blocks: [] +related: [] +created: 2026-05-17 +updated: 2026-05-17 +tags: [] +--- # 0025 — C++ text_editor + file_watcher ## APP Metadata diff --git a/dev/issues/completed/0026-cpp-gl-texture-load.md b/dev/issues/completed/0026-cpp-gl-texture-load.md index b69e1106..a99bc953 100644 --- a/dev/issues/completed/0026-cpp-gl-texture-load.md +++ b/dev/issues/completed/0026-cpp-gl-texture-load.md @@ -1,3 +1,19 @@ +--- +id: "0026" +title: "C++ gl_texture_load" +status: completado +type: feature +domain: + - cpp-stack +scope: multi-app +priority: alta +depends: [] +blocks: [] +related: [] +created: 2026-05-17 +updated: 2026-05-17 +tags: [] +--- # 0026 — C++ gl_texture_load ## APP Metadata diff --git a/dev/issues/completed/0028-cpp-implot3d-3d-viz.md b/dev/issues/completed/0028-cpp-implot3d-3d-viz.md index 75df4b42..b876ea9a 100644 --- a/dev/issues/completed/0028-cpp-implot3d-3d-viz.md +++ b/dev/issues/completed/0028-cpp-implot3d-3d-viz.md @@ -1,3 +1,19 @@ +--- +id: "0028" +title: "C++ ImPlot3D + surface_plot_3d real + scatter_3d" +status: completado +type: feature +domain: + - cpp-stack +scope: multi-app +priority: media +depends: [] +blocks: [] +related: [] +created: 2026-05-17 +updated: 2026-05-17 +tags: [] +--- # 0028 — C++ ImPlot3D + surface_plot_3d real + scatter_3d ## APP Metadata diff --git a/dev/issues/completed/0029-cpp-mesh-viewer.md b/dev/issues/completed/0029-cpp-mesh-viewer.md index e278ec78..cc1f8983 100644 --- a/dev/issues/completed/0029-cpp-mesh-viewer.md +++ b/dev/issues/completed/0029-cpp-mesh-viewer.md @@ -1,3 +1,19 @@ +--- +id: "0029" +title: "C++ mesh_viewer + obj loader + orbit_camera" +status: completado +type: feature +domain: + - cpp-stack +scope: multi-app +priority: media +depends: [] +blocks: [] +related: [] +created: 2026-05-17 +updated: 2026-05-17 +tags: [] +--- # 0029 — C++ mesh_viewer + obj loader + orbit_camera ## APP Metadata diff --git a/dev/issues/completed/002_jupyter_discover_root_dir.md b/dev/issues/completed/002_jupyter_discover_root_dir.md index 2dde1c3d..0c097ae2 100644 --- a/dev/issues/completed/002_jupyter_discover_root_dir.md +++ b/dev/issues/completed/002_jupyter_discover_root_dir.md @@ -1,3 +1,18 @@ +--- +id: "002_jupyter_discover_root_dir" +title: "jupyter_discover: detectar root_dir correctamente" +status: completado +type: feature +domain: [] +scope: multi-app +priority: media +depends: [] +blocks: [] +related: [] +created: 2026-05-17 +updated: 2026-05-17 +tags: [] +--- # jupyter_discover: detectar root_dir correctamente **Componente:** `python/functions/notebook/jupyter_discover.py` diff --git a/dev/issues/completed/0031-cpp-animation-curves.md b/dev/issues/completed/0031-cpp-animation-curves.md index 727842bf..c99f1e09 100644 --- a/dev/issues/completed/0031-cpp-animation-curves.md +++ b/dev/issues/completed/0031-cpp-animation-curves.md @@ -1,3 +1,19 @@ +--- +id: "0031" +title: "C++ animation curves (timeline + bezier_editor + tween_curves)" +status: completado +type: feature +domain: + - cpp-stack +scope: multi-app +priority: media +depends: [] +blocks: [] +related: [] +created: 2026-05-17 +updated: 2026-05-17 +tags: [] +--- # 0031 — C++ animation curves (timeline + bezier_editor + tween_curves) ## APP Metadata diff --git a/dev/issues/completed/0032-cpp-sql-workbench.md b/dev/issues/completed/0032-cpp-sql-workbench.md index 7e60b7b4..89cdae29 100644 --- a/dev/issues/completed/0032-cpp-sql-workbench.md +++ b/dev/issues/completed/0032-cpp-sql-workbench.md @@ -1,3 +1,19 @@ +--- +id: "0032" +title: "C++ sql_workbench" +status: completado +type: feature +domain: + - cpp-stack +scope: multi-app +priority: media +depends: [] +blocks: [] +related: [] +created: 2026-05-17 +updated: 2026-05-17 +tags: [] +--- # 0032 — C++ sql_workbench ## APP Metadata diff --git a/dev/issues/completed/0034-cpp-scientific-viz.md b/dev/issues/completed/0034-cpp-scientific-viz.md index c5136e6e..e18df97d 100644 --- a/dev/issues/completed/0034-cpp-scientific-viz.md +++ b/dev/issues/completed/0034-cpp-scientific-viz.md @@ -1,3 +1,19 @@ +--- +id: "0034" +title: "C++ scientific viz (treemap, sankey, chord, contour, voronoi)" +status: completado +type: feature +domain: + - cpp-stack +scope: multi-app +priority: media +depends: [] +blocks: [] +related: [] +created: 2026-05-17 +updated: 2026-05-17 +tags: [] +--- # 0034 — C++ scientific viz (treemap, sankey, chord, contour, voronoi) ## APP Metadata diff --git a/dev/issues/completed/0037-ioc-regex-extractor.md b/dev/issues/completed/0037-ioc-regex-extractor.md index c0317ea7..458c44f3 100644 --- a/dev/issues/completed/0037-ioc-regex-extractor.md +++ b/dev/issues/completed/0037-ioc-regex-extractor.md @@ -1,3 +1,18 @@ +--- +id: "0037" +title: "IoC regex extractor (cybersecurity)" +status: completado +type: feature +domain: [] +scope: multi-app +priority: alta +depends: [] +blocks: [] +related: [] +created: 2026-05-17 +updated: 2026-05-17 +tags: [] +--- # 0037 — IoC regex extractor (cybersecurity) ## Metadata diff --git a/dev/issues/completed/0038-gliner-entity-extractor.md b/dev/issues/completed/0038-gliner-entity-extractor.md index 16fe0880..5abe9281 100644 --- a/dev/issues/completed/0038-gliner-entity-extractor.md +++ b/dev/issues/completed/0038-gliner-entity-extractor.md @@ -1,3 +1,18 @@ +--- +id: "0038" +title: "GLiNER entity extractor (zero-shot NER)" +status: completado +type: feature +domain: [] +scope: multi-app +priority: alta +depends: [] +blocks: [] +related: [] +created: 2026-05-17 +updated: 2026-05-17 +tags: [] +--- # 0038 — GLiNER entity extractor (zero-shot NER) ## Metadata diff --git a/dev/issues/completed/0039-glirel-relation-extractor.md b/dev/issues/completed/0039-glirel-relation-extractor.md index 2d8ac2e5..4243fd8d 100644 --- a/dev/issues/completed/0039-glirel-relation-extractor.md +++ b/dev/issues/completed/0039-glirel-relation-extractor.md @@ -1,3 +1,18 @@ +--- +id: "0039" +title: "GLiREL relation extractor (zero-shot relations → triplets)" +status: completado +type: feature +domain: [] +scope: multi-app +priority: media +depends: [] +blocks: [] +related: [] +created: 2026-05-17 +updated: 2026-05-17 +tags: [] +--- # 0039 — GLiREL relation extractor (zero-shot relations → triplets) ## Metadata diff --git a/dev/issues/completed/003_jupyter_tools_documentation.md b/dev/issues/completed/003_jupyter_tools_documentation.md index b9f5ba05..4bba1e36 100644 --- a/dev/issues/completed/003_jupyter_tools_documentation.md +++ b/dev/issues/completed/003_jupyter_tools_documentation.md @@ -1,3 +1,18 @@ +--- +id: "003_jupyter_tools_documentation" +title: "Documentación consolidada de herramientas Jupyter" +status: completado +type: feature +domain: [] +scope: multi-app +priority: media +depends: [] +blocks: [] +related: [] +created: 2026-05-17 +updated: 2026-05-17 +tags: [] +--- # Documentación consolidada de herramientas Jupyter **Componente:** `python/functions/notebook/` diff --git a/dev/issues/completed/0040-hybrid-extraction-pipeline.md b/dev/issues/completed/0040-hybrid-extraction-pipeline.md index b5c9aa08..9673f52f 100644 --- a/dev/issues/completed/0040-hybrid-extraction-pipeline.md +++ b/dev/issues/completed/0040-hybrid-extraction-pipeline.md @@ -1,3 +1,18 @@ +--- +id: "0040" +title: "Pipeline hibrido extraccion entidades+relaciones (regex + GLiNER/GLiREL + LLM fallback)" +status: completado +type: feature +domain: [] +scope: multi-app +priority: media +depends: [] +blocks: [] +related: [] +created: 2026-05-17 +updated: 2026-05-17 +tags: [] +--- # 0040 — Pipeline hibrido extraccion entidades+relaciones (regex + GLiNER/GLiREL + LLM fallback) ## Metadata diff --git a/dev/issues/completed/0041-cpp-app-best-practices.md b/dev/issues/completed/0041-cpp-app-best-practices.md index 9fcbf9ac..6dbe4a77 100644 --- a/dev/issues/completed/0041-cpp-app-best-practices.md +++ b/dev/issues/completed/0041-cpp-app-best-practices.md @@ -1,3 +1,19 @@ +--- +id: "0041" +title: "C++ app shell estandarizado: BEST_PRACTICES + AppConfig extendido" +status: completado +type: feature +domain: + - cpp-stack +scope: app-scoped +priority: alta +depends: [] +blocks: [] +related: [] +created: 2026-05-17 +updated: 2026-05-17 +tags: [] +--- # 0041 — C++ app shell estandarizado: BEST_PRACTICES + AppConfig extendido ## Metadata diff --git a/dev/issues/completed/0042-cpp-layout-storage-public.md b/dev/issues/completed/0042-cpp-layout-storage-public.md index 1847f754..9d861f9e 100644 --- a/dev/issues/completed/0042-cpp-layout-storage-public.md +++ b/dev/issues/completed/0042-cpp-layout-storage-public.md @@ -1,9 +1,23 @@ --- id: "0042" title: "C++ layout_storage: extraer y publicar como API reutilizable" -status: completed -created_at: 2026-04-28 -tags: [cpp, ui, refactor, layouts, sqlite] +status: completado +type: feature +domain: + - cpp-stack +scope: multi-app +priority: media +depends: [] +blocks: [] +related: [] +created: 2026-05-17 +updated: 2026-05-17 +tags: + - cpp + - ui + - refactor + - layouts + - sqlite --- # 0042 — C++ layout_storage: extraer y publicar como API reutilizable diff --git a/dev/issues/completed/0043-cpp-apps-standardize-shell.md b/dev/issues/completed/0043-cpp-apps-standardize-shell.md index ecf2303c..0a10df81 100644 --- a/dev/issues/completed/0043-cpp-apps-standardize-shell.md +++ b/dev/issues/completed/0043-cpp-apps-standardize-shell.md @@ -1,3 +1,19 @@ +--- +id: "0043" +title: "Estandarizar shell de las 4 apps C++ (About + Settings + paneles + tokens)" +status: completado +type: refactor +domain: + - cpp-stack +scope: multi-app +priority: alta +depends: [] +blocks: [] +related: [] +created: 2026-05-17 +updated: 2026-05-17 +tags: [] +--- # 0043 — Estandarizar shell de las 4 apps C++ (About + Settings + paneles + tokens) ## Metadata diff --git a/dev/issues/completed/0044-cpp-orphans-audit.md b/dev/issues/completed/0044-cpp-orphans-audit.md index 5940fbab..13b420eb 100644 --- a/dev/issues/completed/0044-cpp-orphans-audit.md +++ b/dev/issues/completed/0044-cpp-orphans-audit.md @@ -1,3 +1,19 @@ +--- +id: "0044" +title: "Auditar 52 funciones C++ huerfanas y poblar uses_functions" +status: completado +type: chore +domain: + - cpp-stack +scope: multi-app +priority: media +depends: [] +blocks: [] +related: [] +created: 2026-05-17 +updated: 2026-05-17 +tags: [] +--- # 0044 — Auditar 52 funciones C++ huerfanas y poblar uses_functions ## Metadata diff --git a/dev/issues/completed/0045-cpp-extract-pure-logic.md b/dev/issues/completed/0045-cpp-extract-pure-logic.md index f7bd9559..c89ad070 100644 --- a/dev/issues/completed/0045-cpp-extract-pure-logic.md +++ b/dev/issues/completed/0045-cpp-extract-pure-logic.md @@ -1,3 +1,20 @@ +--- +id: "0045" +title: "Extraer logica pura de componentes C++ impuros (sql_workbench, process_runner, file_watcher)" +status: completado +type: refactor +domain: + - cpp-stack + - registry-quality +scope: registry-only +priority: media +depends: [] +blocks: [] +related: [] +created: 2026-05-17 +updated: 2026-05-17 +tags: [] +--- # 0045 — Extraer logica pura de componentes C++ impuros (sql_workbench, process_runner, file_watcher) ## Metadata diff --git a/dev/issues/completed/0046-cpp-refactor-raw-imgui.md b/dev/issues/completed/0046-cpp-refactor-raw-imgui.md index dc9339da..f33ec71f 100644 --- a/dev/issues/completed/0046-cpp-refactor-raw-imgui.md +++ b/dev/issues/completed/0046-cpp-refactor-raw-imgui.md @@ -1,3 +1,19 @@ +--- +id: "0046" +title: "Reemplazar raw ImGui en apps por primitivos del registry" +status: completado +type: refactor +domain: + - cpp-stack +scope: multi-app +priority: media +depends: [] +blocks: [] +related: [] +created: 2026-05-17 +updated: 2026-05-17 +tags: [] +--- # 0046 — Reemplazar raw ImGui en apps por primitivos del registry ## Metadata diff --git a/dev/issues/completed/0047-cpp-tests-foundation.md b/dev/issues/completed/0047-cpp-tests-foundation.md index 059453e6..96fc21dc 100644 --- a/dev/issues/completed/0047-cpp-tests-foundation.md +++ b/dev/issues/completed/0047-cpp-tests-foundation.md @@ -1,3 +1,19 @@ +--- +id: "0047" +title: "C++ tests foundation: Catch2 + tests para top-20 primitivos" +status: completado +type: feature +domain: + - cpp-stack +scope: multi-app +priority: alta +depends: [] +blocks: [] +related: [] +created: 2026-05-17 +updated: 2026-05-17 +tags: [] +--- # 0047 — C++ tests foundation: Catch2 + tests para top-20 primitivos ## Metadata diff --git a/dev/issues/completed/0048-cpp-visual-tests-ci-gate.md b/dev/issues/completed/0048-cpp-visual-tests-ci-gate.md index f99fd3c4..7bde9089 100644 --- a/dev/issues/completed/0048-cpp-visual-tests-ci-gate.md +++ b/dev/issues/completed/0048-cpp-visual-tests-ci-gate.md @@ -1,3 +1,19 @@ +--- +id: "0048" +title: "Visual tests via primitives_gallery (golden screenshots) + CI gate para nuevas funciones" +status: completado +type: feature +domain: + - cpp-stack +scope: multi-app +priority: media +depends: [] +blocks: [] +related: [] +created: 2026-05-17 +updated: 2026-05-17 +tags: [] +--- # 0048 — Visual tests via primitives_gallery (golden screenshots) + CI gate para nuevas funciones ## Metadata diff --git a/dev/issues/completed/0049-osint-graph-viewer.md b/dev/issues/completed/0049-osint-graph-viewer.md index f825fb53..a074d125 100644 --- a/dev/issues/completed/0049-osint-graph-viewer.md +++ b/dev/issues/completed/0049-osint-graph-viewer.md @@ -1,3 +1,19 @@ +--- +id: "0049" +title: "OSINT graph viewer + GPU graph rendering system" +status: completado +type: feature +domain: + - osint +scope: multi-app +priority: alta +depends: [] +blocks: [] +related: [] +created: 2026-05-17 +updated: 2026-05-17 +tags: [] +--- # 0049 — OSINT graph viewer + GPU graph rendering system ## Metadata diff --git a/dev/issues/completed/0049a-osint-graph-setup.md b/dev/issues/completed/0049a-osint-graph-setup.md index 1c3cd823..c12c1fb8 100644 --- a/dev/issues/completed/0049a-osint-graph-setup.md +++ b/dev/issues/completed/0049a-osint-graph-setup.md @@ -1,3 +1,19 @@ +--- +id: "0049a" +title: "Setup proyecto `osint_graph` + sub-repo `graph_explorer`" +status: completado +type: feature +domain: + - osint +scope: multi-app +priority: alta +depends: [] +blocks: [] +related: [] +created: 2026-05-17 +updated: 2026-05-17 +tags: [] +--- # 0049a — Setup proyecto `osint_graph` + sub-repo `graph_explorer` ## Metadata diff --git a/dev/issues/completed/0049b-cpp-bump-gl-43.md b/dev/issues/completed/0049b-cpp-bump-gl-43.md index 903b9a86..daf80738 100644 --- a/dev/issues/completed/0049b-cpp-bump-gl-43.md +++ b/dev/issues/completed/0049b-cpp-bump-gl-43.md @@ -1,3 +1,19 @@ +--- +id: "0049b" +title: "Bump OpenGL 3.3 → 4.3 core en `cpp/framework`" +status: completado +type: feature +domain: + - cpp-stack +scope: multi-app +priority: alta +depends: [] +blocks: [] +related: [] +created: 2026-05-17 +updated: 2026-05-17 +tags: [] +--- # 0049b — Bump OpenGL 3.3 → 4.3 core en `cpp/framework` ## Metadata diff --git a/dev/issues/completed/0049c-graph-renderer-tier1.md b/dev/issues/completed/0049c-graph-renderer-tier1.md index 12b757c4..f1e3bd1b 100644 --- a/dev/issues/completed/0049c-graph-renderer-tier1.md +++ b/dev/issues/completed/0049c-graph-renderer-tier1.md @@ -1,3 +1,18 @@ +--- +id: "0049c" +title: "`graph_renderer` Tier 1: RGBA8, orphan buffers, frustum cull, auto-pause" +status: completado +type: feature +domain: [] +scope: multi-app +priority: alta +depends: [] +blocks: [] +related: [] +created: 2026-05-17 +updated: 2026-05-17 +tags: [] +--- # 0049c — `graph_renderer` Tier 1: RGBA8, orphan buffers, frustum cull, auto-pause ## Metadata diff --git a/dev/issues/completed/0049d-graph-edges-vertex-pulling.md b/dev/issues/completed/0049d-graph-edges-vertex-pulling.md index fd5244b0..6aa5b7ac 100644 --- a/dev/issues/completed/0049d-graph-edges-vertex-pulling.md +++ b/dev/issues/completed/0049d-graph-edges-vertex-pulling.md @@ -1,3 +1,18 @@ +--- +id: "0049d" +title: "Aristas via vertex pulling con TBO" +status: completado +type: feature +domain: [] +scope: multi-app +priority: alta +depends: [] +blocks: [] +related: [] +created: 2026-05-17 +updated: 2026-05-17 +tags: [] +--- # 0049d — Aristas via vertex pulling con TBO ## Metadata diff --git a/dev/issues/completed/0049e-graph-types-extended.md b/dev/issues/completed/0049e-graph-types-extended.md index 7dd482b0..2b900e45 100644 --- a/dev/issues/completed/0049e-graph-types-extended.md +++ b/dev/issues/completed/0049e-graph-types-extended.md @@ -1,3 +1,18 @@ +--- +id: "0049e" +title: "Modelo de datos extendido: `GraphNode`/`GraphEdge` + `EntityType`/`RelationType`" +status: completado +type: feature +domain: [] +scope: multi-app +priority: alta +depends: [] +blocks: [] +related: [] +created: 2026-05-17 +updated: 2026-05-17 +tags: [] +--- # 0049e — Modelo de datos extendido: `GraphNode`/`GraphEdge` + `EntityType`/`RelationType` ## Metadata diff --git a/dev/issues/completed/0049f-graph-renderer-symbols.md b/dev/issues/completed/0049f-graph-renderer-symbols.md index 9ecc595b..c14642dd 100644 --- a/dev/issues/completed/0049f-graph-renderer-symbols.md +++ b/dev/issues/completed/0049f-graph-renderer-symbols.md @@ -1,3 +1,18 @@ +--- +id: "0049f" +title: "Renderer extendido: shapes SDF, icon atlas, flechas, edge styles" +status: completado +type: feature +domain: [] +scope: multi-app +priority: alta +depends: [] +blocks: [] +related: [] +created: 2026-05-17 +updated: 2026-05-17 +tags: [] +--- # 0049f — Renderer extendido: shapes SDF, icon atlas, flechas, edge styles ## Metadata diff --git a/dev/issues/completed/0049g-graph-source-operations.md b/dev/issues/completed/0049g-graph-source-operations.md index dd91ef38..d59faadf 100644 --- a/dev/issues/completed/0049g-graph-source-operations.md +++ b/dev/issues/completed/0049g-graph-source-operations.md @@ -1,3 +1,18 @@ +--- +id: "0049g" +title: "`graph_sources`: lector de `operations.db` + abstraccion funcional" +status: completado +type: feature +domain: [] +scope: multi-app +priority: alta +depends: [] +blocks: [] +related: [] +created: 2026-05-17 +updated: 2026-05-17 +tags: [] +--- # 0049g — `graph_sources`: lector de `operations.db` + abstraccion funcional ## Metadata diff --git a/dev/issues/completed/0049h-graph-force-layout-gpu.md b/dev/issues/completed/0049h-graph-force-layout-gpu.md index 137b4899..846091a5 100644 --- a/dev/issues/completed/0049h-graph-force-layout-gpu.md +++ b/dev/issues/completed/0049h-graph-force-layout-gpu.md @@ -1,3 +1,18 @@ +--- +id: "0049h" +title: "`graph_force_layout_gpu`: compute shader + spatial hash" +status: completado +type: feature +domain: [] +scope: multi-app +priority: media +depends: [] +blocks: [] +related: [] +created: 2026-05-17 +updated: 2026-05-17 +tags: [] +--- # 0049h — `graph_force_layout_gpu`: compute shader + spatial hash ## Metadata diff --git a/dev/issues/completed/0049i-graph-layouts-static.md b/dev/issues/completed/0049i-graph-layouts-static.md index 94d0f215..bbf78116 100644 --- a/dev/issues/completed/0049i-graph-layouts-static.md +++ b/dev/issues/completed/0049i-graph-layouts-static.md @@ -1,3 +1,18 @@ +--- +id: "0049i" +title: "`graph_layouts` (radial, hierarchical, fixed) + viewport extendido" +status: completado +type: feature +domain: [] +scope: multi-app +priority: media +depends: [] +blocks: [] +related: [] +created: 2026-05-17 +updated: 2026-05-17 +tags: [] +--- # 0049i — `graph_layouts` (radial, hierarchical, fixed) + viewport extendido ## Metadata diff --git a/dev/issues/completed/0049j-graph-labels.md b/dev/issues/completed/0049j-graph-labels.md index 68175882..48604447 100644 --- a/dev/issues/completed/0049j-graph-labels.md +++ b/dev/issues/completed/0049j-graph-labels.md @@ -1,3 +1,18 @@ +--- +id: "0049j" +title: "`graph_labels`: render de etiquetas con `LabelPolicy`" +status: completado +type: feature +domain: [] +scope: multi-app +priority: media +depends: [] +blocks: [] +related: [] +created: 2026-05-17 +updated: 2026-05-17 +tags: [] +--- # 0049j — `graph_labels`: render de etiquetas con `LabelPolicy` ## Metadata diff --git a/dev/issues/completed/0049k-graph-explorer-app.md b/dev/issues/completed/0049k-graph-explorer-app.md index 532599c7..e78cf032 100644 --- a/dev/issues/completed/0049k-graph-explorer-app.md +++ b/dev/issues/completed/0049k-graph-explorer-app.md @@ -1,3 +1,18 @@ +--- +id: "0049k" +title: "App `graph_explorer` (proyecto `osint_graph`)" +status: completado +type: feature +domain: [] +scope: app-scoped +priority: alta +depends: [] +blocks: [] +related: [] +created: 2026-05-17 +updated: 2026-05-17 +tags: [] +--- # 0049k — App `graph_explorer` (proyecto `osint_graph`) ## Metadata diff --git a/dev/issues/completed/004_jupyter_discover_multiple_instances.md b/dev/issues/completed/004_jupyter_discover_multiple_instances.md index f117f0c0..18832040 100644 --- a/dev/issues/completed/004_jupyter_discover_multiple_instances.md +++ b/dev/issues/completed/004_jupyter_discover_multiple_instances.md @@ -1,3 +1,18 @@ +--- +id: "004_jupyter_discover_multiple_instances" +title: "jupyter_discover: soporte para múltiples instancias" +status: completado +type: feature +domain: [] +scope: multi-app +priority: media +depends: [] +blocks: [] +related: [] +created: 2026-05-17 +updated: 2026-05-17 +tags: [] +--- # jupyter_discover: soporte para múltiples instancias **Componente:** `python/functions/notebook/jupyter_discover.py` diff --git a/dev/issues/completed/0050-jupyter-exec-collab-client-failure.md b/dev/issues/completed/0050-jupyter-exec-collab-client-failure.md index 78743c03..b3089a16 100644 --- a/dev/issues/completed/0050-jupyter-exec-collab-client-failure.md +++ b/dev/issues/completed/0050-jupyter-exec-collab-client-failure.md @@ -1,3 +1,18 @@ +--- +id: "0050" +title: "`jupyter_exec` falla por cliente colaborativo (RESUELTO 2026-05-05)" +status: completado +type: bugfix +domain: [] +scope: multi-app +priority: media +depends: [] +blocks: [] +related: [] +created: 2026-05-17 +updated: 2026-05-17 +tags: [] +--- # 0050 — `jupyter_exec` falla por cliente colaborativo (RESUELTO 2026-05-05) ## Cierre (2026-05-05) diff --git a/dev/issues/completed/0052-footprint-aurgi-extraction.md b/dev/issues/completed/0052-footprint-aurgi-extraction.md index b609bcfe..948a3f03 100644 --- a/dev/issues/completed/0052-footprint-aurgi-extraction.md +++ b/dev/issues/completed/0052-footprint-aurgi-extraction.md @@ -1,8 +1,17 @@ --- +id: "0052" title: "Extracción masiva de footprint_aurgi → registry" -status: completed +status: completado +type: feature +domain: [] +scope: multi-app +priority: alta +depends: [] +blocks: [] +related: [] created: 2026-05-04 -completed: 2026-05-05 +updated: 2026-05-17 +tags: [] --- ## Cierre (2026-05-05) diff --git a/dev/issues/completed/0053-kanban-chat-panel.md b/dev/issues/completed/0053-kanban-chat-panel.md index f9d9f492..e0c686c3 100644 --- a/dev/issues/completed/0053-kanban-chat-panel.md +++ b/dev/issues/completed/0053-kanban-chat-panel.md @@ -1,3 +1,19 @@ +--- +id: "0053" +title: "Chat lateral en apps/kanban via `claude -p`" +status: completado +type: feature +domain: + - kanban +scope: multi-app +priority: media +depends: [] +blocks: [] +related: [] +created: 2026-05-17 +updated: 2026-05-17 +tags: [] +--- # 0053 — Chat lateral en apps/kanban via `claude -p` ## APP Metadata diff --git a/dev/issues/completed/005_jupyter_write_batch.md b/dev/issues/completed/005_jupyter_write_batch.md index 6f839c0b..64401489 100644 --- a/dev/issues/completed/005_jupyter_write_batch.md +++ b/dev/issues/completed/005_jupyter_write_batch.md @@ -1,3 +1,18 @@ +--- +id: "005_jupyter_write_batch" +title: "jupyter_write: crear múltiples celdas en batch" +status: completado +type: feature +domain: [] +scope: multi-app +priority: media +depends: [] +blocks: [] +related: [] +created: 2026-05-17 +updated: 2026-05-17 +tags: [] +--- # jupyter_write: crear múltiples celdas en batch **Componente:** `python/functions/notebook/jupyter_write.py` diff --git a/dev/issues/completed/0062-deprecate-unused-core-functions.md b/dev/issues/completed/0062-deprecate-unused-core-functions.md index 64c62715..5ef182ba 100644 --- a/dev/issues/completed/0062-deprecate-unused-core-functions.md +++ b/dev/issues/completed/0062-deprecate-unused-core-functions.md @@ -1,3 +1,18 @@ +--- +id: "0062" +title: "Politica de deprecacion para funciones del registry sin consumidores" +status: completado +type: feature +domain: [] +scope: multi-app +priority: baja +depends: [] +blocks: [] +related: [] +created: 2026-05-17 +updated: 2026-05-17 +tags: [] +--- # 0062 — Politica de deprecacion para funciones del registry sin consumidores ## APP Metadata diff --git a/dev/issues/completed/0064-registry-mcp-server.md b/dev/issues/completed/0064-registry-mcp-server.md index 13f89041..e73c9cce 100644 --- a/dev/issues/completed/0064-registry-mcp-server.md +++ b/dev/issues/completed/0064-registry-mcp-server.md @@ -1,3 +1,19 @@ +--- +id: "0064" +title: "registry_mcp: servidor MCP que expone registry.db a Claude" +status: completado +type: feature +domain: + - meta +scope: multi-app +priority: alta +depends: [] +blocks: [] +related: [] +created: 2026-05-17 +updated: 2026-05-17 +tags: [] +--- # 0064 — registry_mcp: servidor MCP que expone registry.db a Claude ## APP Metadata diff --git a/dev/issues/completed/006_jupyter_exec_outputs_keyerror.md b/dev/issues/completed/006_jupyter_exec_outputs_keyerror.md index e72bbaca..81d5f545 100644 --- a/dev/issues/completed/006_jupyter_exec_outputs_keyerror.md +++ b/dev/issues/completed/006_jupyter_exec_outputs_keyerror.md @@ -1,3 +1,18 @@ +--- +id: "006_jupyter_exec_outputs_keyerror" +title: "jupyter_exec cell: KeyError 'outputs' en notebooks creados manualmente" +status: completado +type: feature +domain: [] +scope: multi-app +priority: media +depends: [] +blocks: [] +related: [] +created: 2026-05-17 +updated: 2026-05-17 +tags: [] +--- # jupyter_exec cell: KeyError 'outputs' en notebooks creados manualmente **Componente:** `python/functions/notebook/jupyter_exec.py` diff --git a/dev/issues/completed/0073-init_kotlin_app-gradlew-stub-roto.md b/dev/issues/completed/0073-init_kotlin_app-gradlew-stub-roto.md index 86462081..f491496f 100644 --- a/dev/issues/completed/0073-init_kotlin_app-gradlew-stub-roto.md +++ b/dev/issues/completed/0073-init_kotlin_app-gradlew-stub-roto.md @@ -1,11 +1,17 @@ --- -id: 0073 -title: init_kotlin_app genera gradlew stub no funcional -status: pending -priority: high +id: "59" +title: "init_kotlin_app genera gradlew stub no funcional" +status: completado +type: feature +domain: [] +scope: app-scoped +priority: alta +depends: [] +blocks: [] +related: [] created: 2026-05-10 -related_pipelines: [init_kotlin_app_bash_pipelines] -related_apps: [counter_kt] +updated: 2026-05-17 +tags: [] --- ## Sintoma diff --git a/dev/issues/completed/0074-init_kotlin_app-falta-local-properties.md b/dev/issues/completed/0074-init_kotlin_app-falta-local-properties.md index dc04e922..5ac3cb17 100644 --- a/dev/issues/completed/0074-init_kotlin_app-falta-local-properties.md +++ b/dev/issues/completed/0074-init_kotlin_app-falta-local-properties.md @@ -1,11 +1,17 @@ --- -id: 0074 -title: init_kotlin_app no genera local.properties -status: pending -priority: high +id: "60" +title: "init_kotlin_app no genera local.properties" +status: completado +type: feature +domain: [] +scope: app-scoped +priority: alta +depends: [] +blocks: [] +related: [] created: 2026-05-10 -related_pipelines: [init_kotlin_app_bash_pipelines] -related_apps: [counter_kt] +updated: 2026-05-17 +tags: [] --- ## Sintoma diff --git a/dev/issues/completed/0075-init_kotlin_app-AppCompat-theme-falta-dep.md b/dev/issues/completed/0075-init_kotlin_app-AppCompat-theme-falta-dep.md index 978e3cc9..b60b9f67 100644 --- a/dev/issues/completed/0075-init_kotlin_app-AppCompat-theme-falta-dep.md +++ b/dev/issues/completed/0075-init_kotlin_app-AppCompat-theme-falta-dep.md @@ -1,12 +1,17 @@ --- -id: 0075 -title: init_kotlin_app genera AndroidManifest con tema AppCompat sin dep -status: pending -priority: medium +id: "61" +title: "init_kotlin_app genera AndroidManifest con tema AppCompat sin dep" +status: completado +type: feature +domain: [] +scope: app-scoped +priority: media +depends: [] +blocks: [] +related: [] created: 2026-05-10 -related_pipelines: [init_kotlin_app_bash_pipelines] -related_apps: [counter_kt] -fix_applied: 2026-05-10 +updated: 2026-05-17 +tags: [] --- ## Sintoma diff --git a/dev/issues/completed/0078-kotlin-functions-ui-gradle-library.md b/dev/issues/completed/0078-kotlin-functions-ui-gradle-library.md index 032ab1e6..93452a86 100644 --- a/dev/issues/completed/0078-kotlin-functions-ui-gradle-library.md +++ b/dev/issues/completed/0078-kotlin-functions-ui-gradle-library.md @@ -1,19 +1,17 @@ --- -id: 0078 -title: kotlin/functions/ui requiere ser modulo Gradle library para composite build -status: pending -priority: high +id: "0078" +title: "kotlin/functions/ui requiere ser modulo Gradle library para composite build" +status: completado +type: feature +domain: [] +scope: multi-app +priority: alta +depends: [] +blocks: [] +related: [] created: 2026-05-10 -fix_applied: 2026-05-10 -related_functions: - - fn_colors_kt_ui - - fn_spacing_kt_ui - - fn_radius_kt_ui - - fn_typography_kt_ui - - fn_shadows_kt_ui - - fn_tokens_kt_ui - - fn_theme_kt_ui -related_apps: [counter_kt] +updated: 2026-05-17 +tags: [] --- ## Contexto diff --git a/dev/issues/completed/0078-tables-joins-mbql.md b/dev/issues/completed/0078-tables-joins-mbql.md index 7e988da1..91771cad 100644 --- a/dev/issues/completed/0078-tables-joins-mbql.md +++ b/dev/issues/completed/0078-tables-joins-mbql.md @@ -1,11 +1,17 @@ --- -id: 0078 -title: tables playground — joins MBQL-style (fase 9) -status: done -priority: medium +id: "0078" +title: "tables playground — joins MBQL-style (fase 9)" +status: completado +type: feature +domain: [] +scope: multi-app +priority: media +depends: [] +blocks: [] +related: [] created: 2026-05-12 -closed: 2026-05-12 -related_components: [cpp/apps/primitives_gallery/playground/tables, lua_engine, tql] +updated: 2026-05-17 +tags: [] --- ## Contexto diff --git a/dev/issues/completed/0079-tables-drill-ext.md b/dev/issues/completed/0079-tables-drill-ext.md index ba0b2cdb..38f9a602 100644 --- a/dev/issues/completed/0079-tables-drill-ext.md +++ b/dev/issues/completed/0079-tables-drill-ext.md @@ -1,11 +1,17 @@ --- -id: 0079 -title: tables playground — drill-through extendido (fase 10) -status: done -priority: medium +id: "0079" +title: "tables playground — drill-through extendido (fase 10)" +status: completado +type: feature +domain: [] +scope: multi-app +priority: media +depends: [] +blocks: [] +related: [] created: 2026-05-12 -closed: 2026-05-12 -related_components: [cpp/apps/primitives_gallery/playground/tables] +updated: 2026-05-17 +tags: [] --- ## Contexto diff --git a/dev/issues/completed/0080-tables-llm-api.md b/dev/issues/completed/0080-tables-llm-api.md index 8bfed844..87ac6b08 100644 --- a/dev/issues/completed/0080-tables-llm-api.md +++ b/dev/issues/completed/0080-tables-llm-api.md @@ -1,16 +1,17 @@ --- -id: 0080 -title: tables playground — LLM "Ask AI" + TQL/SQL emit (fase 11) -status: done -priority: medium +id: "0080" +title: 'tables playground — LLM "Ask AI" + TQL/SQL emit (fase 11)' +status: completado +type: feature +domain: [] +scope: multi-app +priority: media +depends: [] +blocks: [] +related: [] created: 2026-05-12 -updated: 2026-05-13 -closed: 2026-05-13 -notes: | - pure layer + LLM client + Ask AI modal + DuckDB adapter (FN_TQL_DUCKDB=ON opt-in). - 618 tests pass con DuckDB (round-trip TQL emit -> execute -> match). 603 sin. - e2e linux+windows OK ambos modos. -related_components: [cpp/apps/primitives_gallery/playground/tables, lua_engine, tql, duckdb] +updated: 2026-05-17 +tags: [] --- ## Contexto diff --git a/dev/issues/completed/0081-tables-promote-registry.md b/dev/issues/completed/0081-tables-promote-registry.md index 3d65d9c2..be60bef4 100644 --- a/dev/issues/completed/0081-tables-promote-registry.md +++ b/dev/issues/completed/0081-tables-promote-registry.md @@ -1,23 +1,17 @@ --- -id: 0081 -title: tables playground — promote a registry + migrar apps C++ (fase 12) -status: done -priority: high +id: "0081" +title: "tables playground — promote a registry + migrar apps C++ (fase 12)" +status: completado +type: feature +domain: [] +scope: multi-app +priority: alta +depends: [] +blocks: [] +related: [] created: 2026-05-12 -updated: 2026-05-15 -notes: | - 0081-A DONE: 20 types extraidos a cpp/functions/core/data_table_types.h con .md por type - (17 core + 3 viz). Playground includes via "core/data_table_types.h", no duplicacion. - 603 tests pass, e2e linux+windows OK. - 0081-B..L DONE (2026-05-15): 10 funciones registry (8 core + 2 viz), 1 lib fn_table_viz, - 3 apps migradas (chart_demo no aplica, graph_explorer parcial 1/9, registry_dashboard parcial 8/12), - fn doctor cpp-apps check anadido (BeginTable inline detection: CANDIDATE/MIXED), - docs/TQL.md actualizado con joins, views, main_source, 24 viz tokens, color_rules, - derived columns, fn.* sandbox completo (20 builtins), funciones bloqueadas. - Deuda: sqlite_api + deploy_server NO migrados (Go apps, requieren TS table system aparte); - graph_explorer + registry_dashboard + otras apps C++ marcadas CANDIDATE por fn doctor - (migrar en waves futuras con rama TBD dedicada por app). -related_components: [cpp/apps/primitives_gallery/playground/tables, cpp/functions, fn_framework] +updated: 2026-05-17 +tags: [] --- ## Contexto diff --git a/python/functions/infra/export_hub_icons.md b/python/functions/infra/export_hub_icons.md new file mode 100644 index 00000000..4fd0b119 --- /dev/null +++ b/python/functions/infra/export_hub_icons.md @@ -0,0 +1,70 @@ +--- +name: export_hub_icons +kind: function +lang: py +domain: infra +version: "1.0.0" +purity: impure +signature: "export_hub_icons(out_dir: str, *, size: int = 64, registry_root: str | None = None) -> dict" +description: "Rasteriza iconos PNG para todas las apps C++/imgui del registry y los escribe en un directorio de salida. Consume registry.db para listar apps, lee icon.phosphor + icon.accent de cada app.md y usa la misma logica visual de generate_app_icon (fondo redondeado accent + glyph Phosphor blanco al 70%)." +tags: ["hub", "launcher", "icons", "suite", "png", "phosphor", "imgui", "cpp-windows"] +params: + - name: out_dir + desc: "Directorio de salida donde se escriben los .png. Se crea si no existe. PNGs existentes se sobreescriben." + - name: size + desc: "Lado del cuadrado del PNG en pixels. Default 64. El hub launcher usa 64 para las tarjetas." + - name: registry_root + desc: "Ruta a la raiz del fn_registry. Si es None usa FN_REGISTRY_ROOT env o /home/lucas/fn_registry." +output: "dict con ok=True, count=N (PNGs escritos), out_dir (ruta absoluta), skipped (lista de {name, reason} para apps omitidas)." +uses_functions: + - generate_app_icon_py_infra +uses_types: [] +returns: [] +returns_optional: false +error_type: "error_go_core" +imports: + - cairosvg + - Pillow + - PyYAML + - sqlite3 +tested: false +tests: [] +test_file_path: "" +file_path: "python/functions/infra/export_hub_icons.py" +--- + +## Ejemplo + +```bash +# Exportar iconos 64px al directorio local_files/icons del hub launcher (Windows via WSL) +python/.venv/bin/python3 -c " +import sys; sys.path.insert(0, 'python/functions') +from infra.export_hub_icons import export_hub_icons +print(export_hub_icons('/mnt/c/Users/lucas/Desktop/apps/app_hub_launcher/local_files/icons')) +" + +# Exportar iconos a /tmp para smoke test +python/.venv/bin/python3 -c " +import sys; sys.path.insert(0, 'python/functions') +from infra.export_hub_icons import export_hub_icons +import json +print(json.dumps(export_hub_icons('/tmp/hub_icons_test'), indent=2)) +" + +# Via CLI directo con tamaño personalizado +cd /home/lucas/fn_registry +python/.venv/bin/python3 python/functions/infra/export_hub_icons.py /tmp/hub_icons --size 128 +``` + +## Cuando usarla + +Despues de compilar y desplegar `app_hub_launcher` a Windows Desktop, antes de lanzar la app: ejecutar esta funcion para generar los PNGs que el hub carga via `fn::gl_texture_load` al arrancar. Tambien util para regenerar los iconos tras cambiar el campo `icon:` en algun `app.md` o tras añadir una nueva app imgui al registry. + +## Gotchas + +- Requiere que `sources/phosphor-core/` este clonado en la raiz del registry (`git clone --depth=1 https://github.com/phosphor-icons/core.git sources/phosphor-core`). Si falta, todas las apps se omiten con "Phosphor SVG not found". +- Las apps sin campo `icon:` en su `app.md` usan el icono por defecto (`app-window`, accent `#64748b`) — no se omiten. +- `cairosvg` requiere `libcairo2` instalado en el sistema (`apt install libcairo2-dev` en Debian/Ubuntu). En WSL suele estar disponible si se uso anteriormente `generate_app_icon`. +- El campo `icon.phosphor` debe ser el nombre del glyph Phosphor **sin sufijo de weight** (ej. `"chart-bar"`, no `"chart-bar-fill"`). El sufijo `-fill.svg` se añade internamente. +- `out_dir` en rutas Windows desde WSL debe usar `/mnt/c/...` — no rutas Win32 directas. +- Apps con `dir_path` que apuntan a rutas fuera del registry (ej. `cpp/apps/shaders_lab`) se tratan igual: `root / dir_path / "app.md"`. Si la app no esta clonada localmente, su `app.md` falta y se omite. diff --git a/python/functions/infra/export_hub_icons.py b/python/functions/infra/export_hub_icons.py new file mode 100644 index 00000000..0aa193e0 --- /dev/null +++ b/python/functions/infra/export_hub_icons.py @@ -0,0 +1,185 @@ +"""export_hub_icons — rasteriza iconos PNG para todas las apps C++/imgui del registry. + +Para cada app cpp/imgui registrada en registry.db lee el bloque `icon:` de su +app.md (phosphor + accent), rasteriza un PNG cuadrado usando la misma logica +visual que generate_app_icon y lo escribe en out_dir/.png. + +El directorio de salida lo consume app_hub_launcher via fn::gl_texture_load. +""" + +from __future__ import annotations + +import os +import sqlite3 +import sys +from pathlib import Path +from typing import Any + +from infra.generate_app_icon import _find_registry_root, _make_icon_image + +DEFAULT_PHOSPHOR = "app-window" +DEFAULT_ACCENT = "#64748b" +DEFAULT_SIZE = 64 + + +def _read_frontmatter(md_path: Path) -> dict[str, Any]: + """Parse YAML frontmatter from a .md file. Returns {} on any error.""" + try: + import yaml + + text = md_path.read_text(encoding="utf-8") + if not text.startswith("---"): + return {} + end = text.find("\n---", 3) + if end == -1: + return {} + yaml_block = text[3:end].strip() + data = yaml.safe_load(yaml_block) + return data if isinstance(data, dict) else {} + except Exception as exc: + print(f"[export_hub_icons] WARN: could not parse {md_path}: {exc}", file=sys.stderr) + return {} + + +def export_hub_icons( + out_dir: str, + *, + size: int = DEFAULT_SIZE, + registry_root: str | None = None, +) -> dict: + """Rasteriza iconos PNG para todas las apps C++/imgui del registry. + + Consulta registry.db buscando apps con lang='cpp' AND framework='imgui', + lee el bloque icon: de cada app.md (phosphor + accent), y escribe un PNG + cuadrado de size x size pixels en out_dir/.png usando el mismo estilo + visual de generate_app_icon: fondo redondeado del color accent con glyph + Phosphor blanco centrado al 70%. + + Si una app.md no existe, no tiene icono declarado o el SVG Phosphor no se + encuentra, el app se omite (skipped) y el proceso continua con las demas. + + Args: + out_dir: Directorio de salida. Se crea si no existe. Los PNGs existentes + se sobreescriben. + size: Lado del cuadrado del PNG en pixels. Default 64. + registry_root: Ruta a la raiz del fn_registry. Si es None, usa la variable + de entorno FN_REGISTRY_ROOT o /home/lucas/fn_registry como fallback. + + Returns: + { + "ok": True, + "count": N, # PNGs escritos correctamente + "out_dir": "", # ruta absoluta del directorio de salida + "skipped": [ # apps omitidas con razon + {"name": "...", "reason": "..."}, + ... + ] + } + """ + root = _find_registry_root(registry_root) + + db_path = root / "registry.db" + if not db_path.exists(): + raise FileNotFoundError(f"registry.db not found at {db_path}") + + con = sqlite3.connect(str(db_path)) + con.row_factory = sqlite3.Row + try: + rows = con.execute( + "SELECT id, name, dir_path FROM apps" + " WHERE lang='cpp' AND framework='imgui'" + " ORDER BY name" + ).fetchall() + finally: + con.close() + + phosphor_assets = root / "sources" / "phosphor-core" / "assets" + + out_path = Path(out_dir).resolve() + out_path.mkdir(parents=True, exist_ok=True) + + count = 0 + skipped: list[dict[str, str]] = [] + + for row in rows: + app_name: str = row["name"] + dir_path: str = row["dir_path"] + + # --- Leer app.md --- + md_path = root / dir_path / "app.md" + if not md_path.exists(): + msg = f"app.md missing at {md_path}" + print(f"[export_hub_icons] SKIP {app_name}: {msg}", file=sys.stderr) + skipped.append({"name": app_name, "reason": msg}) + continue + + fm = _read_frontmatter(md_path) + if not fm: + msg = "app.md missing or malformed frontmatter" + print(f"[export_hub_icons] SKIP {app_name}: {msg}", file=sys.stderr) + skipped.append({"name": app_name, "reason": msg}) + continue + + icon_block = fm.get("icon") + if isinstance(icon_block, dict): + phosphor_name = icon_block.get("phosphor") or DEFAULT_PHOSPHOR + accent_hex = icon_block.get("accent") or DEFAULT_ACCENT + else: + phosphor_name = DEFAULT_PHOSPHOR + accent_hex = DEFAULT_ACCENT + + # --- Localizar SVG Phosphor --- + svg_path = phosphor_assets / "fill" / f"{phosphor_name}-fill.svg" + if not svg_path.exists(): + msg = f"Phosphor SVG not found: {svg_path}" + print(f"[export_hub_icons] SKIP {app_name}: {msg}", file=sys.stderr) + skipped.append({"name": app_name, "reason": msg}) + continue + + # --- Rasterizar y guardar PNG --- + try: + img = _make_icon_image(svg_path, accent_hex, size) + png_out = out_path / f"{app_name}.png" + img.save(str(png_out), format="PNG") + count += 1 + except Exception as exc: + msg = f"render error: {exc}" + print(f"[export_hub_icons] SKIP {app_name}: {msg}", file=sys.stderr) + skipped.append({"name": app_name, "reason": msg}) + continue + + return { + "ok": True, + "count": count, + "out_dir": str(out_path), + "skipped": skipped, + } + + +if __name__ == "__main__": + import argparse + import json + + parser = argparse.ArgumentParser( + description="Export PNG icons for all cpp/imgui apps to a directory." + ) + parser.add_argument("out_dir", help="Destination directory for .png files") + parser.add_argument( + "--size", + type=int, + default=DEFAULT_SIZE, + help=f"Icon side in pixels (default {DEFAULT_SIZE})", + ) + parser.add_argument( + "--registry-root", + default=None, + help="Path to fn_registry root (default: FN_REGISTRY_ROOT env or /home/lucas/fn_registry)", + ) + args = parser.parse_args() + + result = export_hub_icons( + args.out_dir, + size=args.size, + registry_root=args.registry_root, + ) + print(json.dumps(result, indent=2)) diff --git a/python/functions/infra/generate_app_icon.py b/python/functions/infra/generate_app_icon.py index f63bdb3d..e8902c6b 100644 --- a/python/functions/infra/generate_app_icon.py +++ b/python/functions/infra/generate_app_icon.py @@ -2,6 +2,11 @@ Rasteriza un icono Phosphor SVG sobre un fondo redondeado del color accent y exporta un .ico con multiples resoluciones (16, 24, 32, 48, 64, 128, 256). + +Funciones publicas reutilizables: + _find_registry_root — localiza la raiz del registry + _render_glyph_white — rasteriza un SVG Phosphor como glyph blanco RGBA + _make_icon_image — compone fondo redondeado + glyph en un PIL.Image """ import io import os @@ -14,8 +19,23 @@ from PIL import Image, ImageDraw DEFAULT_SIZES = [16, 24, 32, 48, 64, 128, 256] -def _find_registry_root() -> Path: - """Descubre la raiz del registry caminando hacia arriba hasta encontrar registry.db.""" +def _find_registry_root(registry_root: str | None = None) -> Path: + """Descubre la raiz del registry. + + Prioridad: argumento explicito > FN_REGISTRY_ROOT env > caminar hacia arriba + desde el archivo hasta encontrar registry.db. + + Args: + registry_root: Ruta absoluta opcional. Si se pasa, se devuelve directamente. + + Returns: + Path resuelto a la raiz del registry. + + Raises: + FileNotFoundError: Si no se puede localizar registry.db. + """ + if registry_root is not None: + return Path(registry_root).resolve() env_root = os.environ.get("FN_REGISTRY_ROOT") if env_root: return Path(env_root).resolve() @@ -35,7 +55,15 @@ def _hex_to_rgb(h: str) -> tuple[int, int, int]: def _render_glyph_white(svg_path: Path, size: int) -> Image.Image: - """Renderiza el SVG Phosphor como glyph blanco sobre fondo transparente.""" + """Renderiza el SVG Phosphor como glyph blanco sobre fondo transparente. + + Args: + svg_path: Ruta al archivo .svg de Phosphor. + size: Ancho/alto en pixels del output. + + Returns: + Imagen RGBA con el glyph en blanco sobre fondo transparente. + """ svg = svg_path.read_text(encoding="utf-8") # Phosphor usa fill="currentColor" — forzar blanco. svg = svg.replace('fill="currentColor"', 'fill="#ffffff"') @@ -48,7 +76,16 @@ def _render_glyph_white(svg_path: Path, size: int) -> Image.Image: def _make_icon_image(svg_path: Path, accent_hex: str, size: int) -> Image.Image: - """Compone fondo redondeado con color accent + glyph blanco centrado al 70%.""" + """Compone fondo redondeado con color accent + glyph blanco centrado al 70%. + + Args: + svg_path: Ruta al archivo .svg de Phosphor. + accent_hex: Color de fondo en formato "#RRGGBB". + size: Ancho/alto en pixels del canvas de salida. + + Returns: + Imagen RGBA lista para guardar como PNG o ICO. + """ bg_color = _hex_to_rgb(accent_hex) + (255,) canvas = Image.new("RGBA", (size, size), (0, 0, 0, 0)) draw = ImageDraw.Draw(canvas) @@ -113,8 +150,8 @@ def generate_app_icon( # Resolver raiz de phosphor if phosphor_root is None: - registry_root = _find_registry_root() - phosphor_assets = registry_root / "sources" / "phosphor-core" / "assets" + _root = _find_registry_root() + phosphor_assets = _root / "sources" / "phosphor-core" / "assets" else: phosphor_assets = Path(phosphor_root) diff --git a/python/functions/pipelines/migrate_issues_frontmatter.md b/python/functions/pipelines/migrate_issues_frontmatter.md new file mode 100644 index 00000000..b40b0e55 --- /dev/null +++ b/python/functions/pipelines/migrate_issues_frontmatter.md @@ -0,0 +1,122 @@ +--- +name: migrate_issues_frontmatter +kind: pipeline +lang: py +domain: pipelines +version: "1.0.0" +purity: impure +signature: "def migrate_issues_frontmatter(issues_dir: str, backup_dir: str = '', dry_run: bool = False) -> dict" +description: "Migra dev/issues/*.md de metadata inline (**Key:** value) a frontmatter YAML canonico (issue 0100). Idempotente: archivos ya migrados (id + domain + scope presentes) se saltan. Archivos con frontmatter parcial reciben merge de claves faltantes. Infiere domain, scope, type y priority por heuristicas de nombre de archivo." +tags: [registry-quality, frontmatter, chore, dev-issues, migration, registry] +uses_functions: + - extract_frontmatter_py_core +uses_types: [] +returns: [] +returns_optional: false +error_type: "error_go_core" +imports: + - json + - os + - re + - shutil + - sys + - datetime + - pathlib + - typing +tested: false +params: + - name: issues_dir + desc: "Ruta al directorio de issues (ej. 'dev/issues'). Se escanean *.md directos y completed/*.md." + - name: backup_dir + desc: "Directorio donde copiar los originales antes de escribir. Default: /.backup_pre_0100/. Pasar '' para usar el default." + - name: dry_run + desc: "Si True, calcula cambios pero no escribe archivos ni crea backups." +output: "dict con claves: migrated (N archivos migrados desde cero), merged (N archivos con frontmatter parcial completado), skipped (N ya completos), warnings (lista de strings), files (lista de resultados por archivo con action/domain_inferred/scope_inferred/warnings)." +file_path: "python/functions/pipelines/migrate_issues_frontmatter.py" +notes: | + Pipeline impuro: muta archivos .md en disco y crea backups. + + Heuristicas de domain (primer match gana, multi-tag posible): + cpp-stack — filename contiene cpp-, imgui, glfw, glsl, altsnap + kanban — filename contiene kanban + trading — filename contiene trading + gamedev — filename contiene gamedev + osint — filename contiene osint, odr- + data-ingest — filename contiene metabase, bigquery, datafactory, navegator, cdp- + notify — filename contiene notify, telegram, matrix + imagegen — filename contiene imagegen, sd-cpp, stable-diffusion + registry-quality — filename contiene audit-, registry-first, uses_functions, nested-app-md + meta — filename contiene autonomous, e2e-validation, registry-call, delegation, capability, call-monitor, mcp- + deploy — filename contiene deploy, vps + dev-ux — filename contiene fn-run, gradle_run, dev- + browser — filename contiene browser, chrome, cdp- + apps-infra — filename contiene datahub, app-hub, launcher, app-locations + frontend — filename contiene frontend, react + default — lista vacia + warning + + Heuristicas de scope: + roadmap -> cross-stack + extract-|migrate-|audit- -> registry-only + type=app o -app- en filename -> app-scoped + default -> multi-app + + Heuristicas de type (si no viene del inline): + roadmap -> epic + audit-|cleanup- -> chore + fix-|bugfix- -> bugfix + default -> feature + + Heuristicas de priority (si no viene del inline): + mtime < 14 dias -> alta + else -> media + + Formatos inline reconocidos: + **Status:** value (y variantes: Estado, Tipo, Prioridad, Created, Depends, Blocks, Related) + | **Campo** | valor | (tabla markdown) + + El backup se crea solo UNA vez por archivo (si ya existe el backup, no sobreescribe). + Segunda ejecucion = 0 cambios si los archivos ya tienen id + domain + scope. +--- + +## Ejemplo + +```bash +# Siempre hacer dry-run primero para revisar +cd /home/lucas/fn_registry +python/.venv/bin/python3 python/functions/pipelines/migrate_issues_frontmatter.py dev/issues --dry-run + +# Aplicar migracion real +python/.venv/bin/python3 python/functions/pipelines/migrate_issues_frontmatter.py dev/issues + +# O via fn run +./fn run migrate_issues_frontmatter_py_pipelines +``` + +```python +import sys +sys.path.insert(0, "python/functions") +from pipelines.migrate_issues_frontmatter import migrate_issues_frontmatter + +# Dry run +result = migrate_issues_frontmatter("dev/issues", dry_run=True) +print(result["migrated"], "to migrate,", result["skipped"], "already done") + +# Apply +result = migrate_issues_frontmatter("dev/issues") +print(result["warnings"]) +``` + +## Cuando usarla + +Cuando necesites migrar `dev/issues/*.md` de inline `**Key:** value` a frontmatter YAML canonico. Ejecucion one-shot por proyecto; despues de la primera pasada, correr periodicamente para validar issues nuevos (idempotente). + +Tambien util al crear un proyecto nuevo que adopte el formato issues/ de fn_registry: copia los .md y lanza el pipeline para homogeneizar. + +## Gotchas + +- **Muta archivos en disco**. Siempre correr con `--dry-run` primero para revisar la salida. +- **Backup dir no es gitignored por defecto**. Anadir `.backup_pre_0100/` al `.gitignore` del repo si no se quiere versionar. +- **Heuristicas de domain son best-effort**. Revisar warnings al final de la ejecucion; los archivos sin domain inferido quedan con `domain: []` y aparecen en warnings. +- **Frontmatter parcial se completa sin sobreescribir**. Si ya tienes `status: done` en el YAML, no se toca. Solo se anaden las claves ausentes. +- **El backup se escribe antes que el nuevo contenido**. Si el proceso se interrumpe a mitad, los backups son los originales correctos. +- **No valida el schema canonico de los tipos**. Si una issue tiene `type: weird-value`, se guarda tal cual y no hay warning. La validacion es responsabilidad de `fn doctor issues` (issue 0102, pendiente). diff --git a/python/functions/pipelines/migrate_issues_frontmatter.py b/python/functions/pipelines/migrate_issues_frontmatter.py new file mode 100644 index 00000000..55b68d99 --- /dev/null +++ b/python/functions/pipelines/migrate_issues_frontmatter.py @@ -0,0 +1,646 @@ +#!/usr/bin/env python3 +"""migrate_issues_frontmatter — migrate dev/issues/*.md from inline **Key:** value +metadata to canonical YAML frontmatter (issue 0100). + +Idempotent: files that already have id + domain + scope in frontmatter are skipped. +Files with partial frontmatter get missing keys merged in without overwriting existing ones. +""" + +from __future__ import annotations + +import json +import os +import re +import shutil +import sys +from datetime import date +from pathlib import Path +from typing import Any + +# --------------------------------------------------------------------------- +# Registry path setup +# --------------------------------------------------------------------------- + +def _find_registry_root() -> Path: + here = Path(__file__).resolve() + for parent in (here, *here.parents): + if (parent / "registry.db").exists(): + return parent + return Path.cwd() + + +_REGISTRY_ROOT = _find_registry_root() +sys.path.insert(0, str(_REGISTRY_ROOT / "python" / "functions")) + +from core.core import extract_frontmatter # noqa: E402 + +# --------------------------------------------------------------------------- +# Constants +# --------------------------------------------------------------------------- + +TODAY = date.today().isoformat() + +_SKIP_NAMES = {"README.md", "template.md", "README", "template"} + +_STATUS_ALIASES = { + "pendiente": "pendiente", + "pending": "pendiente", + "in-progress": "in-progress", + "en-progreso": "in-progress", + "en_progreso": "in-progress", + "bloqueado": "bloqueado", + "blocked": "bloqueado", + "completado": "completado", + "done": "completado", + "completed": "completado", + "deferred": "deferred", + "diferido": "deferred", + "closed": "completado", +} + +_TYPE_ALIASES = { + "app": "app", + "feature": "feature", + "bugfix": "bugfix", + "bug": "bugfix", + "refactor": "refactor", + "chore": "chore", + "docs": "docs", + "doc": "docs", + "spike": "spike", + "epic": "epic", + "infra": "infra", + "planning": "planning", +} + +_PRIORITY_ALIASES = { + "alta": "alta", + "high": "alta", + "media": "media", + "medium": "media", + "baja": "baja", + "low": "baja", +} + +# --------------------------------------------------------------------------- +# Heuristics +# --------------------------------------------------------------------------- + +def _infer_domain(filename: str) -> list[str]: + """Return list of canonical domain tags based on filename heuristics.""" + f = filename.lower() + domains: list[str] = [] + + if re.search(r"^cpp-|(-cpp-)|imgui|glfw|glsl|altsnap|sizemove", f): + domains.append("cpp-stack") + if re.search(r"^kanban-|kanban", f): + domains.append("kanban") + if re.search(r"^trading-|0088[a-z]?-trading", f): + domains.append("trading") + if re.search(r"^gamedev-|0072[a-z]?-gamedev", f): + domains.append("gamedev") + if re.search(r"osint|odr-", f): + domains.append("osint") + if re.search(r"metabase|bigquery|datafactory|data-factory|navegator|cdp-", f): + domains.append("data-ingest") + if re.search(r"notify|telegram|matrix", f): + domains.append("notify") + if re.search(r"imagegen|sd-cpp|stable-diffusion", f): + domains.append("imagegen") + if re.search(r"dag-engine|dagu", f): + if "cpp" in f or "imgui" in f: + domains.append("cpp-stack") + else: + domains.append("data-ingest") + if re.search(r"audit-|registry-first|uses.functions|nested-app-md", f): + domains.append("registry-quality") + if re.search(r"autonomous|e2e-validation|registry-call|delegation|capability|call-monitor|mcp-", f): + domains.append("meta") + if re.search(r"deploy|vps", f): + domains.append("deploy") + if re.search(r"fn-run|gradle.run|(? str: + f = filename.lower() + if re.search(r"roadmap", f): + return "cross-stack" + if re.search(r"extract-|migrate-|audit-", f): + return "registry-only" + if inline_type == "app" or re.search(r"-app[-.]|app-", f): + return "app-scoped" + return "multi-app" + + +def _infer_type(filename: str) -> str: + f = filename.lower() + if re.search(r"roadmap", f): + return "epic" + if re.search(r"audit-|cleanup-", f): + return "chore" + if re.search(r"fix-|bugfix-|bug-", f): + return "bugfix" + return "feature" + + +def _infer_priority_from_mtime(path: Path) -> str: + mtime = path.stat().st_mtime + mtime_date = date.fromtimestamp(mtime) + delta = (date.today() - mtime_date).days + if delta <= 14: + return "alta" + return "media" + + +# --------------------------------------------------------------------------- +# Inline parser +# --------------------------------------------------------------------------- + +_H1_RE = re.compile(r"^#\s+(.+)$", re.MULTILINE) +_BOLD_KEY_RE = re.compile(r"^\*\*([A-Za-z]+)\*\*:\s*(.*)$") +_TABLE_META_RE = re.compile(r"^\|\s*\*\*([A-Za-z]+)\*\*\s*\|\s*(.+?)\s*\|") +# Match "NNNN" or "NNNN — rest" +_ID_FROM_H1_RE = re.compile(r"^(\d{4}[a-z]?)\s*[—-]\s*(.+)$") +_ISSUE_REF_RE = re.compile(r"\b(\d{4}[a-z]?)\b") + + +def _extract_h1_title(content: str) -> tuple[str, str]: + """Return (issue_id, clean_title) from H1. Falls back to ('', content first line).""" + m = _H1_RE.search(content) + if not m: + return "", "" + h1 = m.group(1).strip() + id_m = _ID_FROM_H1_RE.match(h1) + if id_m: + return id_m.group(1), id_m.group(2).strip() + return "", h1 + + +def _parse_inline_meta(content: str) -> dict[str, str]: + """Parse **Key:** value lines and table metadata from first ~40 lines.""" + meta: dict[str, str] = {} + lines = content.splitlines()[:40] + for line in lines: + # Bold inline: **Status:** value + bm = _BOLD_KEY_RE.match(line.strip()) + if bm: + key = bm.group(1).lower() + val = bm.group(2).strip() + meta[key] = val + continue + # Table row: | **Estado** | value | + tm = _TABLE_META_RE.match(line.strip()) + if tm: + key = tm.group(1).lower() + val = tm.group(2).strip() + # Strip markdown bold from value + val = re.sub(r"\*\*(.+?)\*\*", r"\1", val) + meta[key] = val + return meta + + +def _parse_issue_ids(raw: str) -> list[str]: + """Extract issue IDs (NNNN or NNNNa) from a raw string like '0096, 0097 — DONE'.""" + if not raw or raw.strip() in ("—", "-", "", "ninguna", "none"): + return [] + return _ISSUE_REF_RE.findall(raw) + + +def _normalize_status(raw: str) -> str: + raw = raw.lower().strip() + # extract first word-token + token = re.split(r"[\s,;—-]", raw)[0] + return _STATUS_ALIASES.get(token, _STATUS_ALIASES.get(raw, "pendiente")) + + +def _normalize_type(raw: str) -> str: + raw = raw.lower().strip() + # strip trailing annotation like "feature — apps/kanban/" + token = re.split(r"[\s,;—-]", raw)[0] + return _TYPE_ALIASES.get(token, "") + + +def _normalize_priority(raw: str) -> str: + raw = raw.lower().strip() + token = re.split(r"[\s,;]", raw)[0] + return _PRIORITY_ALIASES.get(token, "") + + +# --------------------------------------------------------------------------- +# Frontmatter builder +# --------------------------------------------------------------------------- + +def _build_frontmatter( + issue_id: str, + title: str, + status: str, + type_: str, + domain: list[str], + scope: str, + priority: str, + depends: list[str], + blocks: list[str], + related: list[str], + created: str, + updated: str, + tags: list[str], +) -> str: + """Render canonical YAML frontmatter block as a string.""" + lines: list[str] = ["---"] + lines.append(f"id: \"{issue_id}\"") + lines.append(f"title: \"{title}\"") + lines.append(f"status: {status}") + lines.append(f"type: {type_}") + + if domain: + lines.append("domain:") + for d in domain: + lines.append(f" - {d}") + else: + lines.append("domain: []") + + lines.append(f"scope: {scope}") + lines.append(f"priority: {priority}") + + if depends: + lines.append("depends:") + for d in depends: + lines.append(f" - \"{d}\"") + else: + lines.append("depends: []") + + if blocks: + lines.append("blocks:") + for b in blocks: + lines.append(f" - \"{b}\"") + else: + lines.append("blocks: []") + + if related: + lines.append("related:") + for r in related: + lines.append(f" - \"{r}\"") + else: + lines.append("related: []") + + lines.append(f"created: {created}") + lines.append(f"updated: {updated}") + + if tags: + lines.append("tags:") + for t in tags: + lines.append(f" - {t}") + else: + lines.append("tags: []") + + lines.append("---") + return "\n".join(lines) + "\n" + + +# --------------------------------------------------------------------------- +# Per-file processing +# --------------------------------------------------------------------------- + +FileResult = dict[str, Any] + + +def _process_file( + path: Path, + backup_dir: Path | None, + dry_run: bool, +) -> FileResult: + result: FileResult = { + "path": str(path), + "action": "skipped", + "domain_inferred": [], + "scope_inferred": "", + "warnings": [], + } + + content = path.read_text(encoding="utf-8") + body_without_fm, existing_fm = extract_frontmatter(content) + + # Determine issue_id from filename + stem = path.stem # e.g. "0099-datahub-app-launcher" + id_from_file_m = re.match(r"^(\d{4}[a-z]?)", stem) + file_issue_id = id_from_file_m.group(1) if id_from_file_m else stem + + # Check if already fully migrated + if existing_fm and isinstance(existing_fm, dict): + fm = existing_fm + has_id = "id" in fm + has_domain = "domain" in fm + has_scope = "scope" in fm + if has_id and has_domain and has_scope: + result["action"] = "skipped" + return result + # Partial frontmatter — merge missing keys + result["action"] = "merged" + _fill_missing_keys(path, fm, body_without_fm, file_issue_id, result, backup_dir, dry_run) + return result + + # No frontmatter: parse inline and build canonical + result["action"] = "migrated" + _migrate_from_inline(path, content, file_issue_id, result, backup_dir, dry_run) + return result + + +def _fill_missing_keys( + path: Path, + fm: dict, + body: str, + file_issue_id: str, + result: FileResult, + backup_dir: Path | None, + dry_run: bool, +) -> None: + """Merge missing canonical keys into an existing partial frontmatter.""" + warnings = result["warnings"] + filename = path.name + + issue_id = str(fm.get("id", file_issue_id)) + title = str(fm.get("title", _extract_h1_title(body)[1] or filename)) + status = _normalize_status(str(fm.get("status", fm.get("estado", "pendiente")))) + type_ = _normalize_type(str(fm.get("type", fm.get("tipo", "")))) + if not type_: + type_ = _infer_type(filename) + if not type_: + warnings.append(f"type missing, inferred: {type_ or '(empty)'}") + + domain_raw = fm.get("domain", fm.get("dominio", [])) + if isinstance(domain_raw, str): + domain = [domain_raw] if domain_raw else [] + elif isinstance(domain_raw, list): + domain = domain_raw + else: + domain = [] + + if not domain: + domain = _infer_domain(filename) + result["domain_inferred"] = domain + if not domain: + warnings.append("domain could not be inferred") + + scope = str(fm.get("scope", "")) + if not scope: + scope = _infer_scope(filename, type_) + result["scope_inferred"] = scope + + priority = _normalize_priority(str(fm.get("priority", fm.get("priority", "")))) + if not priority: + priority = _infer_priority_from_mtime(path) + warnings.append(f"priority missing, inferred from mtime: {priority}") + + depends = _coerce_id_list(fm.get("depends", fm.get("depends_on", []))) + blocks = _coerce_id_list(fm.get("blocks", [])) + related = _coerce_id_list(fm.get("related", [])) + created = str(fm.get("created", TODAY)) + tags_raw = fm.get("tags", []) + tags = tags_raw if isinstance(tags_raw, list) else [] + + new_fm = _build_frontmatter( + issue_id=issue_id, + title=title, + status=status, + type_=type_, + domain=domain, + scope=scope, + priority=priority, + depends=depends, + blocks=blocks, + related=related, + created=created, + updated=TODAY, + tags=tags, + ) + new_content = new_fm + body + + if not dry_run: + _backup_file(path, backup_dir) + path.write_text(new_content, encoding="utf-8") + + +def _coerce_id_list(val: Any) -> list[str]: + if isinstance(val, list): + return [str(v) for v in val] + if isinstance(val, str): + return _parse_issue_ids(val) + return [] + + +def _migrate_from_inline( + path: Path, + content: str, + file_issue_id: str, + result: FileResult, + backup_dir: Path | None, + dry_run: bool, +) -> None: + """Parse inline metadata and write YAML frontmatter.""" + warnings = result["warnings"] + filename = path.name + + inline = _parse_inline_meta(content) + h1_id, h1_title = _extract_h1_title(content) + issue_id = h1_id or file_issue_id + title = h1_title or filename + + # Status + status_raw = inline.get("status", inline.get("estado", "")) + status = _normalize_status(status_raw) if status_raw else "pendiente" + + # Type + type_raw = inline.get("type", inline.get("tipo", "")) + type_ = _normalize_type(type_raw) if type_raw else "" + if not type_: + type_ = _infer_type(filename) + warnings.append(f"type missing/unknown ({type_raw!r}), inferred: {type_}") + + # Domain + domain_raw = inline.get("domain", inline.get("dominio", "")) + if domain_raw and domain_raw not in ("—", "-"): + domain = [d.strip() for d in re.split(r"[,;]", domain_raw) if d.strip()] + else: + domain = _infer_domain(filename) + result["domain_inferred"] = domain + if not domain: + warnings.append("domain could not be inferred from filename") + + # Scope + scope_raw = inline.get("scope", inline.get("alcance", "")) + scope = scope_raw if scope_raw and scope_raw not in ("—", "-") else _infer_scope(filename, type_) + result["scope_inferred"] = scope + + # Priority + priority_raw = inline.get("priority", inline.get("prioridad", "")) + priority = _normalize_priority(priority_raw) if priority_raw else "" + if not priority: + priority = _infer_priority_from_mtime(path) + warnings.append(f"priority missing, inferred from mtime: {priority}") + + # Depends / Blocks / Related + depends = _parse_issue_ids(inline.get("depends", inline.get("depends_on", inline.get("depende", "")))) + blocks = _parse_issue_ids(inline.get("blocks", inline.get("bloquea", ""))) + related = _parse_issue_ids(inline.get("related", inline.get("relacionado", inline.get("relacionados", "")))) + + # Created date + created_raw = inline.get("created", inline.get("fecha", "")) + created = created_raw.strip() if created_raw and re.match(r"\d{4}-\d{2}-\d{2}", created_raw) else TODAY + + new_fm = _build_frontmatter( + issue_id=issue_id, + title=title, + status=status, + type_=type_, + domain=domain, + scope=scope, + priority=priority, + depends=depends, + blocks=blocks, + related=related, + created=created, + updated=TODAY, + tags=[], + ) + new_content = new_fm + content + + if not dry_run: + _backup_file(path, backup_dir) + path.write_text(new_content, encoding="utf-8") + + +def _backup_file(path: Path, backup_dir: Path | None) -> None: + if backup_dir is None: + return + backup_dir.mkdir(parents=True, exist_ok=True) + dest = backup_dir / path.name + if not dest.exists(): + shutil.copy2(path, dest) + + +# --------------------------------------------------------------------------- +# Public API +# --------------------------------------------------------------------------- + +def migrate_issues_frontmatter( + issues_dir: str, + backup_dir: str = "", + dry_run: bool = False, +) -> dict[str, Any]: + """Migrate dev/issues/*.md from inline metadata to canonical YAML frontmatter. + + Args: + issues_dir: Path to the issues directory (e.g. "dev/issues"). + backup_dir: Where to copy originals before writing. Defaults to + /.backup_pre_0100/. Pass "" for default. + dry_run: If True, compute changes but do not write files. + + Returns: + { + "migrated": N, + "merged": N, + "skipped": N, + "warnings": [...], + "files": [{"path": ..., "action": ..., "domain_inferred": ..., "scope_inferred": ..., "warnings": [...]}, ...] + } + """ + issues_path = Path(issues_dir).expanduser() + if not issues_path.is_dir(): + raise FileNotFoundError(f"issues_dir not found: {issues_path}") + + # Determine backup directory + if dry_run: + bk_path = None + elif backup_dir: + bk_path = Path(backup_dir).expanduser() + else: + bk_path = issues_path / ".backup_pre_0100" + + # Collect all .md files from issues_dir and issues_dir/completed/ + all_files: list[Path] = [] + for md in sorted(issues_path.glob("*.md")): + if md.name in _SKIP_NAMES: + continue + all_files.append(md) + completed_dir = issues_path / "completed" + if completed_dir.is_dir(): + for md in sorted(completed_dir.glob("*.md")): + if md.name in _SKIP_NAMES: + continue + all_files.append(md) + + results: list[FileResult] = [] + all_warnings: list[str] = [] + + for path in all_files: + try: + r = _process_file(path, bk_path, dry_run) + except Exception as e: + r = { + "path": str(path), + "action": "warning", + "domain_inferred": [], + "scope_inferred": "", + "warnings": [f"ERROR: {e}"], + } + if r["warnings"]: + for w in r["warnings"]: + all_warnings.append(f"{path.name}: {w}") + results.append(r) + + migrated = sum(1 for r in results if r["action"] == "migrated") + merged = sum(1 for r in results if r["action"] == "merged") + skipped = sum(1 for r in results if r["action"] == "skipped") + warnings_count = sum(1 for r in results if r["action"] == "warning") + + # Summary table + prefix = "[DRY RUN] " if dry_run else "" + print(f"\n{prefix}migrate_issues_frontmatter summary") + print(f" issues_dir : {issues_path}") + print(f" files found: {len(results)}") + print(f" migrated : {migrated}") + print(f" merged : {merged}") + print(f" skipped : {skipped}") + print(f" warnings : {len(all_warnings)}") + if all_warnings: + print("\nWarnings:") + for w in all_warnings: + print(f" - {w}") + + return { + "migrated": migrated, + "merged": merged, + "skipped": skipped, + "warnings": all_warnings, + "files": results, + } + + +# --------------------------------------------------------------------------- +# CLI entry +# --------------------------------------------------------------------------- + +if __name__ == "__main__": + issues_dir_arg = sys.argv[1] if len(sys.argv) > 1 else "dev/issues" + dry = "--dry-run" in sys.argv + result = migrate_issues_frontmatter(issues_dir_arg, dry_run=dry) + print(json.dumps(result, ensure_ascii=False, indent=2))