feat(0130): kanban_cpp v2 — backend Go + 5 registry parser fns + epic/sub-issues

Registry (issue 0130a):
- 5 fns infra: parse_issue_md, write_issue_md, scan_issues_dir,
  scan_flows_dir, watch_dir_fsnotify
- 3 tipos: Issue, Flow, FsEvent
- Tests round-trip + scan reales + watcher fsnotify (all PASS)
- Capability group 'kanban' nuevo (docs/capabilities/kanban.md)

Apps:
- apps/kanban_cpp/ (sub-repo) — frontend ImGui: board drag-drop,
  flows, filters, detail con CSV editors
- apps/kanban_cpp/backend/ — Go service port 8487: REST + SSE +
  fsnotify watcher, parser bidireccional MD<->SQLite cache

Issues:
- dev/issues/0130-kanban-cpp-v2.md (epic)
- 0130a parser, 0130b backend, 0130c frontend

CMakeLists.txt: add_subdirectory apps/kanban_cpp (registrado por
init_cpp_app scaffolder).

End-to-end verde: backend devuelve 189 issues + 9 flows; PATCH a
/api/issues/{id} reescribe .md (solo frontmatter, body intacto);
frontend --self-test exit 0; tests Go infra 5/5 PASS.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Egutierrez
2026-05-22 22:20:15 +02:00
parent e387c91b4c
commit c468b24d2b
31 changed files with 1706 additions and 9 deletions
+38
View File
@@ -0,0 +1,38 @@
---
name: flow
lang: go
domain: infra
version: "0.1.0"
algebraic: product
definition: |
type Flow struct {
ID string `yaml:"id"`
Title string `yaml:"title,omitempty"`
Status string `yaml:"status,omitempty"`
Kind string `yaml:"kind,omitempty"`
Tags []string `yaml:"tags,omitempty"`
Name string `yaml:"name,omitempty"`
Priority string `yaml:"priority,omitempty"`
FilePath string `yaml:"-"`
MtimeNs int64 `yaml:"-"`
}
description: "Frontmatter YAML de un archivo dev/flows/*.md. Campos de runtime (FilePath, MtimeNs) no se serializan en YAML."
tags: [flow, frontmatter, yaml, kanban, dev-ux, registry]
uses_types: []
file_path: "functions/infra/flow_type.go"
---
## Ejemplo
```go
f := infra.Flow{
ID: "0001",
Name: "hn-top-stories",
Status: "pending",
Tags: []string{"scraping", "news"},
}
```
## Notas
Producido por `scan_flows_dir_go_infra`. Los flows del registry usan campos variados en su frontmatter — el struct cubre el subconjunto comun: id/name/title/status/kind/tags/priority. Campos desconocidos se ignoran silenciosamente por yaml.Unmarshal.
+30
View File
@@ -0,0 +1,30 @@
---
name: fs_event
lang: go
domain: infra
version: "0.1.0"
algebraic: product
definition: |
type FsEvent struct {
Path string
Op string // "create" | "write" | "remove" | "rename"
}
description: "Evento del watcher de sistema de archivos. Op es uno de: create, write, remove, rename."
tags: [watcher, fsnotify, event, filesystem, kanban, dev-ux]
uses_types: []
file_path: "functions/infra/fs_event_type.go"
---
## Ejemplo
```go
// Recibido desde el canal de watch_dir_fsnotify_go_infra:
ev := infra.FsEvent{
Path: "/home/lucas/fn_registry/dev/issues/0130a-kanban-cpp-v2-parser.md",
Op: "write",
}
```
## Notas
Producido por `watch_dir_fsnotify_go_infra`. El canal emite un evento por archivo afectado tras el debounce de 200ms. Si se producen multiples operaciones sobre el mismo path en la ventana de debounce, se emite solo la ultima operacion.
+51
View File
@@ -0,0 +1,51 @@
---
name: issue
lang: go
domain: infra
version: "0.1.0"
algebraic: product
definition: |
type Issue struct {
ID string `yaml:"id"`
Title string `yaml:"title"`
Status string `yaml:"status"`
Type string `yaml:"type"`
Domain []string `yaml:"domain"`
Scope string `yaml:"scope"`
Priority string `yaml:"priority"`
Depends []string `yaml:"depends"`
Blocks []string `yaml:"blocks"`
Related []string `yaml:"related"`
Tags []string `yaml:"tags"`
Flow string `yaml:"flow,omitempty"`
Created string `yaml:"created"`
Updated string `yaml:"updated"`
FilePath string `yaml:"-"`
MtimeNs int64 `yaml:"-"`
Completed bool `yaml:"-"`
}
description: "Frontmatter YAML de un archivo dev/issues/*.md. Campos de runtime (FilePath, MtimeNs, Completed) no se serializan en YAML."
tags: [issue, frontmatter, yaml, kanban, dev-ux, registry]
uses_types: []
file_path: "functions/infra/issue_type.go"
---
## Ejemplo
```go
iss := infra.Issue{
ID: "0130",
Title: "Kanban C++ v2",
Status: "pendiente",
Priority: "alta",
Domain: []string{"cpp-stack", "apps-infra"},
Scope: "multi-app",
Tags: []string{"kanban", "cpp"},
Created: "2026-05-22",
Updated: "2026-05-22",
}
```
## Notas
Producido por `parse_issue_md_go_infra`. Los campos `Depends`, `Blocks`, `Related`, `Tags`, `Domain` se deserializan como `[]string` — si el YAML los omite, quedan como slice vacio (no nil). `Completed` se deduce del path (contiene `/completed/`), no del frontmatter.