feat: initial scaffold kanban_cpp v0.1.0

C++ ImGui kanban for steering LLM agents. Six panels (Board, Calendar,
Dashboard, Agent runs, Worktrees, DoD inspector) wired to registry
functions http_request, kpi_card, sparkline, agent_runs_timeline,
dod_evidence_panel. Backend Go on :8403 (independent operations.db from
kanban_web).
This commit is contained in:
Egutierrez
2026-05-18 18:46:09 +02:00
commit a76ec74338
42 changed files with 5922 additions and 0 deletions
+51
View File
@@ -0,0 +1,51 @@
CREATE TABLE IF NOT EXISTS columns (
id TEXT PRIMARY KEY,
name TEXT NOT NULL,
position INTEGER NOT NULL DEFAULT 0,
location TEXT NOT NULL DEFAULT 'board' CHECK(location IN ('board','sidebar')),
width INTEGER NOT NULL DEFAULT 300,
wip_limit INTEGER NOT NULL DEFAULT 0,
created_at TEXT NOT NULL
);
CREATE TABLE IF NOT EXISTS cards (
id TEXT PRIMARY KEY,
requester TEXT NOT NULL DEFAULT '',
title TEXT NOT NULL,
description TEXT NOT NULL DEFAULT '',
color TEXT NOT NULL DEFAULT '',
column_id TEXT NOT NULL REFERENCES columns(id) ON DELETE CASCADE,
position INTEGER NOT NULL DEFAULT 0,
locked INTEGER NOT NULL DEFAULT 0,
created_at TEXT NOT NULL,
updated_at TEXT NOT NULL
);
CREATE TABLE IF NOT EXISTS card_column_history (
id TEXT PRIMARY KEY,
card_id TEXT NOT NULL REFERENCES cards(id) ON DELETE CASCADE,
column_id TEXT NOT NULL,
entered_at TEXT NOT NULL,
exited_at TEXT
);
CREATE TABLE IF NOT EXISTS card_lock_history (
id TEXT PRIMARY KEY,
card_id TEXT NOT NULL REFERENCES cards(id) ON DELETE CASCADE,
locked_at TEXT NOT NULL,
unlocked_at TEXT
);
CREATE TABLE IF NOT EXISTS users (
id TEXT PRIMARY KEY,
username TEXT NOT NULL UNIQUE,
password_hash TEXT NOT NULL,
display_name TEXT NOT NULL DEFAULT '',
created_at TEXT NOT NULL
);
CREATE INDEX IF NOT EXISTS idx_cards_column ON cards(column_id);
CREATE INDEX IF NOT EXISTS idx_cards_position ON cards(column_id, position);
CREATE INDEX IF NOT EXISTS idx_history_card ON card_column_history(card_id);
CREATE INDEX IF NOT EXISTS idx_columns_position ON columns(position);
CREATE INDEX IF NOT EXISTS idx_lock_history_card ON card_lock_history(card_id);
+4
View File
@@ -0,0 +1,4 @@
-- Add stickers column to cards. Idempotent ALTER pattern in db.go ensureColumns.
-- Stickers persist as JSON array: [{"emoji":"🔥","x":0.5,"y":0.5}, ...]
-- x, y in [0, 1] relative to card dimensions for resize survival.
ALTER TABLE cards ADD COLUMN stickers TEXT NOT NULL DEFAULT '[]';
@@ -0,0 +1,6 @@
-- Columnas extra de `columns` (location, width, wip_limit, is_done).
-- Antes vivian en ensureColumns Go. Reextraidas a migration por consistencia.
ALTER TABLE columns ADD COLUMN location TEXT NOT NULL DEFAULT 'board';
ALTER TABLE columns ADD COLUMN width INTEGER NOT NULL DEFAULT 300;
ALTER TABLE columns ADD COLUMN wip_limit INTEGER NOT NULL DEFAULT 0;
ALTER TABLE columns ADD COLUMN is_done INTEGER NOT NULL DEFAULT 0;
+9
View File
@@ -0,0 +1,9 @@
-- Columnas extra de `cards` (color, locked, assignee_id, completed_at, deleted_at, tags).
-- Antes vivian en ensureColumns Go. La columna stickers va aparte en 002.
ALTER TABLE cards ADD COLUMN color TEXT NOT NULL DEFAULT '';
ALTER TABLE cards ADD COLUMN locked INTEGER NOT NULL DEFAULT 0;
ALTER TABLE cards ADD COLUMN assignee_id TEXT;
ALTER TABLE cards ADD COLUMN completed_at TEXT;
ALTER TABLE cards ADD COLUMN deleted_at TEXT;
ALTER TABLE cards ADD COLUMN tags TEXT NOT NULL DEFAULT '[]';
CREATE INDEX IF NOT EXISTS idx_cards_assignee ON cards(assignee_id);
+3
View File
@@ -0,0 +1,3 @@
-- actor_id en histories (quien movió la card / quien bloqueó).
ALTER TABLE card_column_history ADD COLUMN actor_id TEXT;
ALTER TABLE card_lock_history ADD COLUMN actor_id TEXT;
+2
View File
@@ -0,0 +1,2 @@
-- Color del avatar del usuario (Mantine color name o '#rrggbb' personalizado).
ALTER TABLE users ADD COLUMN color TEXT NOT NULL DEFAULT '';
+11
View File
@@ -0,0 +1,11 @@
-- Eventos cronologicos por card. Complementa column_history (moves) y lock_history (locks).
-- Captura: created, assigned, unassigned, title_changed, description_changed, color_changed, tags_changed.
CREATE TABLE IF NOT EXISTS card_events (
id TEXT PRIMARY KEY,
card_id TEXT NOT NULL REFERENCES cards(id) ON DELETE CASCADE,
kind TEXT NOT NULL,
actor_id TEXT,
payload TEXT NOT NULL DEFAULT '{}',
created_at TEXT NOT NULL
);
CREATE INDEX IF NOT EXISTS idx_card_events_card ON card_events(card_id, created_at);
+7
View File
@@ -0,0 +1,7 @@
-- ID secuencial humano por card. Distinto del id hex (PK interna).
-- Backfill por orden de creacion.
ALTER TABLE cards ADD COLUMN seq_num INTEGER NOT NULL DEFAULT 0;
UPDATE cards SET seq_num = (
SELECT COUNT(*) FROM cards c2 WHERE c2.created_at <= cards.created_at
) WHERE seq_num = 0;
CREATE UNIQUE INDEX IF NOT EXISTS idx_cards_seq_num ON cards(seq_num) WHERE seq_num > 0;
+4
View File
@@ -0,0 +1,4 @@
-- Deadline opcional por card. Fecha RFC3339 (precision dia o instante).
-- NULL = sin deadline (default). El frontend muestra countdown hasta la fecha.
ALTER TABLE cards ADD COLUMN deadline TEXT;
CREATE INDEX IF NOT EXISTS idx_cards_deadline ON cards(deadline) WHERE deadline IS NOT NULL;
+14
View File
@@ -0,0 +1,14 @@
-- Per-card chat messages (human-to-human comments).
-- Distinct from card_events (which records system events like title_changed)
-- and from /api/chat (which is the board-level LLM chat).
CREATE TABLE IF NOT EXISTS card_messages (
id TEXT PRIMARY KEY,
card_id TEXT NOT NULL,
author_id TEXT,
body TEXT NOT NULL,
created_at TEXT NOT NULL,
FOREIGN KEY (card_id) REFERENCES cards(id) ON DELETE CASCADE
);
CREATE INDEX IF NOT EXISTS idx_card_messages_card ON card_messages(card_id, created_at);