Files
fn_registry/dev/issues/0109m-issues-api-service.md
T
egutierrez 7eb7b3d0c8 chore: snapshot WIP previo + flow 0008 + 7 sub-issues (0112-0119)
Snapshot de WIP acumulado de sesiones previas antes de merge wave 1
del flow 0008 (kanban_cpp + agent_runner_api + DoD schema).

Incluye:
- dev/flows/0008-kanban-cpp-and-agent-workflows.md
- dev/issues/0112-0119*.md (7 sub-issues)
- WIP previo en cmd/fn/doctor.go, registry/*, modules/, cpp/, etc.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-18 18:17:08 +02:00

5.3 KiB

id, title, status, type, domain, scope, priority, depends, blocks, related, created, updated, tags
id title status type domain scope priority depends blocks related created updated tags
0109m issues_api service: HTTP backend para issues+flows (skill_tree, kanban, dashboards) pendiente feature
meta
apps-infra
app-scoped media
0109h2
0109
0106
2026-05-18 2026-05-18
service
go
http
issues
flows
api

0109m — issues_api service

Por que

skill_tree.exe corre en Windows nativo. Necesita leer dev/issues/*.md + dev/flows/*.md que viven en WSL ~/fn_registry/. Opciones:

Solucion Pro Contra
UNC \\wsl.localhost\Ubuntu\home\lucas\fn_registry Cero infra extra Hardcodea distro/user. No funciona si WSL caido.
Service HTTP (este issue) Robusto, reusable por otras apps (kanban, web dashboard) Mas piezas que mantener
Embeber YAML parser + nested fields Self-contained Mucha logica duplicada

Fix UNC ya esta hecho (0109l). Pero el patron canonico del registry son services (services_api, sqlite_api, registry_api). Este issue formaliza issues_api.

Spec

Service Go HTTP en puerto 8486. Patron identico a services_api (issue 0106).

Endpoints

  • GET /api/health{"status":"ok"}
  • GET /api/issues → array JSON con TODOS los issues (open + completed)
  • GET /api/issues/:id → un issue concreto con body markdown completo
  • GET /api/flows → array JSON con todos los flows
  • GET /api/flows/:id → un flow concreto
  • GET /api/stats → counts por status/domain/type (agregados para Dashboard)
  • POST /api/issues → crea nuevo issue (escribe .md). Body: {id, title, type, domain, depends, body, dod}. Devuelve {path}.
  • POST /api/flows → crea nuevo flow. Mismo shape adaptado a frontmatter de flows.

Schema JSON issue

{
  "id": "0109",
  "title": "...",
  "status": "pendiente",
  "status_eff": "pendiente_unlocked",
  "type": "epic",
  "domain": ["meta", "cpp-stack"],
  "priority": "media",
  "depends": [],
  "blocks": [],
  "related": ["0085"],
  "tags": ["skill-tree"],
  "created": "2026-05-17",
  "updated": "2026-05-18",
  "file_path": "dev/issues/0109-skill-tree-app-roadmap.md",
  "body_md": "(opcional, solo en /api/issues/:id)",
  "dod": [{"text":"App existe","done":true}, ...]
}

Implementacion

// apps/issues_api/main.go
package main

import (
    "encoding/json"
    "net/http"
    "log"
    "os"
    // reusa funciones del registry:
    // - extract_frontmatter (Go port; existe extract_frontmatter_py_core, pero
    //   en C++ existe parse_md_frontmatter_cpp_core — necesitamos Go port o
    //   reusar yaml.v3 directo aqui).
)

func main() {
    root := os.Getenv("FN_REGISTRY_ROOT")
    if root == "" { log.Fatal("FN_REGISTRY_ROOT not set") }
    mux := http.NewServeMux()
    mux.HandleFunc("/api/health", health)
    mux.HandleFunc("/api/issues", listIssues(root))
    mux.HandleFunc("/api/issues/", showIssue(root))
    mux.HandleFunc("/api/flows", listFlows(root))
    mux.HandleFunc("/api/flows/", showFlow(root))
    mux.HandleFunc("/api/stats", stats(root))
    log.Fatal(http.ListenAndServe(":8486", mux))
}

Frontmatter: existe extract_frontmatter_py_core (Python). Hace falta:

  • Opcion A: crear parse_md_frontmatter_go_core (port del C++). Reusable por otros services Go.
  • Opcion B: usar gopkg.in/yaml.v3 directo dentro de issues_api.

Recomiendo A — Go port reusable. Pattern: header parse_md_frontmatter.go en functions/core/.

Frontmatter service: block en app.md

service:
  port: 8486
  health_endpoint: /api/health
  health_timeout_s: 3
  systemd_unit: issues_api.service
  systemd_scope: user
  restart_policy: always
  runtime: systemd-user
  pc_targets:
    - aurgi-pc
    - home-wsl
  is_local_only: false

Skill_tree consume

Cambio en skill_tree/main.cpp:

  • Si discover_registry_root() falla, intentar HTTP http://localhost:8486/api/issues.
  • Si responde 200 → parsear JSON y poblar g_scan.nodes.
  • Fallback a UNC + file scan si no.

Cliente HTTP en C++:

  • Linux: libcurl (ya disponible) o popen("curl ...").
  • Windows: WinHTTP nativo o curl.exe (Windows 10+ trae curl).
  • Mas simple: spawn curl.exe -s http://... y parsear stdout (nlohmann json — habria que vendor).

Sub-issues

  • 0109m1 — crear parse_md_frontmatter_go_core port del C++ (mismas semanticas, mismos tests).
  • 0109m2 — scaffolder issues_api app + service block + systemd unit.
  • 0109m3 — implementar endpoints GET (list, show, stats).
  • 0109m4 — implementar POST issues + POST flows (escribir .md valido).
  • 0109m5 — cliente HTTP en skill_tree + fallback chain (env > walk > UNC > HTTP).

Beneficios cross-app

Una vez issues_api existe, reutilizan:

  • kanban (issue 0058 sync) podria leer/sync issues.
  • Frontend web dashboard ya tendria backend.
  • CI/automation puede crear issues via POST en lugar de editar .md a mano.
  • services_monitor mostrara issues_api como service mas (auto via tag: service).

DoD

  • apps/issues_api/ scaffoldada via /cpp-app ?? no — Go service via /app.
  • Endpoints listed devuelven JSON valido.
  • systemd unit instalado (issues_api.service).
  • Visible en services_monitor como service activo.
  • skill_tree consume HTTP cuando esta disponible, cae a UNC/file si no.
  • Tests Go basicos (list, show, post).