commit 02ac470eff298a045170a413a3b7d0e5b3678af7 Author: Robin Choice Date: Tue May 19 23:30:19 2026 +0200 Initial commit — Kanban-App migriert von ~/.kanban nach ~/dev/kanban Self-contained HTML-Kanban als operative Single Source of Truth für alle laufenden Projekte. Visualisiert das Ringsystem. Stack: Vanilla HTML/CSS/JS, localStorage, kein Build, kein Backend Server: ~/dev/kanban/server.sh (Python http.server auf Port 8765) Spec: ~/dev/kanban/SPEC.md 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.6 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..86da10b --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +node_modules/ +.DS_Store +*.log +backup-*.html + diff --git a/SPEC.md b/SPEC.md new file mode 100644 index 0000000..04784e7 --- /dev/null +++ b/SPEC.md @@ -0,0 +1,537 @@ +# Kanban — Spec & Architektur + +**Datei:** `/Users/robinchoice/dev/kanban/index.html` (eine Datei, kein Build) +**Server:** `/Users/robinchoice/dev/kanban/server.sh` — static-file server aus `~` auf Port 8765 +**Aufruf:** `http://localhost:8765/dev/kanban/index.html` (Server muss laufen für MD-Viewer; sonst funktioniert das Board trotzdem) +**State:** Browser `localStorage` + +--- + +## Zweck + +Single Source of Truth für alle laufenden Projekte. Self-contained HTML mit Kanban-Methodik (3 Spalten, Expedite-Swimlane, Class of Service, WIP-Limits, Little's Law, Monte Carlo). +Visualisiert das Ringsystem von Robin (Ring 0–3, vier Workspace-Gruppen, ~16 Boards). + +--- + +## Layout + +``` +┌──────────────┬──────────────────────────────────────┬──────────────┐ +│ SIDEBAR │ MAIN (Overview / Board / Analytics) │ IDEEN │ +│ links │ │ rechts │ +│ │ │ │ +│ Gruppen │ • Header (Titel, Goal, Pills) │ • Input │ +│ + Boards │ • Tabs │ • Filter │ +│ + Aktionen │ • View-Body │ • Liste │ +│ 210 px │ flex:1 │ 280 px │ +└──────────────┴──────────────────────────────────────┴──────────────┘ +``` + +Banner oben (rot/amber) wenn auf `file://` statt `localhost:8765` — mit Switch-Button. + +--- + +## Drei Views (Tabs in der Reihenfolge: Overview · Board · Analytics) + +### Overview (Default) + +Hero-Block + 5 Sektionen, alle Felder editierbar: + +| Element | Quelle | Edit | +|---|---|---| +| Hero-Icon (96×96, rounded) | `overview.icon` (path) | bei Bild-Fail Emoji-Fallback in Board-Farbe | +| Hero-Name | `board.name` | im Board-Header editierbar | +| Hero-Tagline (lila, kursiv) | `overview.tagline` | Click + tippen | +| Hero-Description (2-3 Sätze) | `overview.description` | Click + tippen | +| Badges: Ring, Gruppe, Typ | live + `overview.type` | type editierbar | +| Launch-Cards Grid | `overview.launches[]` | **Single-Click öffnet URL** (oder MD-Viewer wenn `.md`). **Doppelklick auf Text editiert.** `×` löscht. | +| Was bisher geschah | `overview.summary` | Click + tippen | +| Tech-Stack | `overview.stack[]` | Pill mit `×`, `+ Tech` Input | +| Hosting · IDs · Pfade | `overview.info[]` | Label + Value editierbar, Copy-Btn, `×`, `+ Zeile` | +| 🔒 Secrets · Keys | `overview.secrets[]` | Label + Value editierbar, masked-Toggle (Auge), Copy-Btn, `×`, `+ Secret` | +| ⌘ Quick-Commands | `overview.commands[]` | Label + Cmd editierbar, Copy-Btn, `×`, `+ Command` | + +### Board + +3-Spalten-Kanban + Expedite-Swimlane darüber. + +| Spalte | Farbe | WIP-Limit | +|---|---|---| +| Ready | amber | — | +| In Progress | blau | per Board (Pill im Header editierbar) | +| Done | grün | — | + +**Expedite-Swimlane:** horizontale Reihe über dem Board mit 3 Zonen (deckungsgleich mit Spalten). Tasks mit `cos:'expedite'` erscheinen NUR in der Zone, nicht im normalen col-body. Drag zwischen Zonen behält Expedite. Drag in col-body demotet. Drag von col-body in Zone promoted. + +**Karten-Aktionen** (sichtbar bei Hover, oben rechts): +- ⚑ Blocker togglen (`task.blocked`) — Karte rot +- ↗ Promote-to-Board — öffnet Add-Board-Modal mit Task-Titel vorbelegt +- × Löschen + +**Auto-Aging:** Karte > SLE-Tage in einer Spalte → roter Glow + "ÜBERFÄLLIG"-Label. Done-Karten werden nicht alt gezeigt. + +**Add-Card:** `+ Karte…` Input am Spalten-Ende. Enter fügt hinzu, Esc blurt. + +### Analytics + +| KPI | Berechnung | Farbe | +|---|---|---| +| WIP | `count(wip)` gegen `wipLimit` | rot/amber/blau | +| Cycle Time ⌀ | `WIP / Throughput × 7` (Tage) | blau | +| Queue ETA | `(WIP+Ready) / Throughput × 7` (Tage bis Queue leer) | teal | +| Flow Efficiency | `WIP / (WIP+Ready) × 100%` | grün/amber/rot | +| Remaining | `WIP + Ready` | neutral | + +**Throughput-Quelle:** automatisch `realThroughput()` aus Done-Cards der letzten 14 Tage (mit `task.doneAt`). Fallback `board.throughput` wenn keine History. Status-Pill ("↻ Real" grün vs. "⊘ Statisch" grau). + +**Monte Carlo:** 8.000 Runs, Varianz ±60%, gibt P50/P75/P85/P95 Wochen + Datum. Live-Input für Throughput-Override. + +**Active Blockers:** alle Tasks mit `task.blocked === true`. + +**SLE:** vergleicht Cycle Time mit `board.sle.days`. + +--- + +## Sidebar (links) + +Gruppen-Sections, dynamisch aus `GROUPS` + `BOARDS` gerendert. Meta-Gruppe (Ring 0) ist visuell hervorgehoben (lila Gradient, Glow, `◉`-Bullet). + +| Element | Verhalten | +|---|---| +| Gruppen-Section | Drop-Zone für Board-Drag (board.group ändern) | +| Gruppen-Header (`s-group`) | draggable — Reihenfolge der Gruppen ändern (persistiert in `kanban_groups`) | +| Nav-Item (Board) | Klick = aktivieren; draggable in andere Gruppe oder vor andere Nav-Items (Reihenfolge in `kanban_board_order`) | +| Ring-Badge (R0/R1p/R1w/R2/R3/?) | Klick togglet durch Ring-Werte | +| Badge (Count) | `remaining(b)` mit Color-Code (rot=Blocker, blau=WIP, grau=neutral) | +| `×` (nur user-erstellt) | löscht das Board | + +**Unten:** +- `+ Board` → Modal: Name, Goal, Gruppe (oder + Neue Gruppe), Farb-Picker (8 Optionen) +- `+ Gruppe` → `prompt()` für Namen; leere Gruppen werden gezeigt +- `↺ Reset` → aktuelles Board auf DEFAULTS zurück; bei user-erstellten Boards: löschen + +--- + +## Ideen-Pinnwand (rechts) + +| Element | Verhalten | +|---|---| +| Input + Enter | neue Idee am Anfang einfügen, Tag aus aktivem Filter | +| Filter-Buttons (Alle/Projekt/Erkenntnis/Später) | filtern Liste + setzen Default-Tag | +| Idee-Card | hover-Buttons: `→` (Promote-Modal) und `✕` (löschen); **draggable** auf col-body → erstellt Task | +| Drop-Zonen (erscheinen beim Card-Drag aus Board) | 📂 Projekt / 💡 Erkenntnis / 🕒 Später / ○ ohne Label — droppen entfernt Task aus Board und legt Idee an | + +**Seed:** 35 Ideen (v1=20 Projekt, v2=15 Erkenntnis, v3=+16 aus _archive). Versionierung via `kanban_ideas_seeded` Key. + +--- + +## Datenmodell + +### Task +```js +{ + t: 'Titel', // required + blocked: true, // optional — Karte rot, ⚑ aktiv + cos: 'expedite' | 'fixed', // optional — Class of Service + movedAt: 1779580800000, // Timestamp letzter Spaltenwechsel (für Aging) + doneAt: 1779580800000, // Timestamp bei Wechsel nach Done (für Throughput) + age: 14, // optional — manuell überschriebenes Aging (rare) + note: 'Notiz', // optional — graue Sub-Zeile +} +``` + +### Board +```js +{ + name: 'Döner-App', + goal: 'Beschreibung', + group: 'Code', // Sidebar-Gruppe + color: '#f87171', // Dot-Farbe + ring: '0' | '1p' | '1w' | '2' | '3' | '?', + wipLimit: 3, // editierbar via Pill + throughput: 2, // editierbar via Pill (Fallback wenn keine Done-History) + sle: { days: 14, p: 85 }, // days editierbar via Pill + cols: [ + { id: 'ready', label: 'Ready', tasks: [...] }, + { id: 'wip', label: 'In Progress', tasks: [...] }, + { id: 'done', label: 'Done', tasks: [...] }, + ], + focus: 'Fixstern-Text', // editierbar im Header + overview: { // optional + icon: 'assets/...png', + tagline: '...', + description: '...', + summary: '...', + type: 'ios-app' | 'web' | 'meta' | ..., + launches: [{label, sub, url, icon}], + stack: ['...'], + info: [{label, value}], + secrets: [{label, value, masked}], + commands: [{label, cmd}], + }, + userCreated: true, // nur bei UI-erstellten Boards +} +``` + +### Idea +```js +{ + id: 1013, + text: '...', + tag: 'projekt' | 'erkenntnis' | 'spaeter', // optional + created: '17.05.' | 'archive/...' | 'journal/...', +} +``` + +### State-Keys in localStorage + +| Key | Inhalt | +|---|---| +| `kanban_v2` | `{[boardId]: {cols, focus, [overrides], [userCreated-Meta]}}` | +| `kanban_groups` | `['Meta','Code',...]` | +| `kanban_board_order` | `{[group]: [id1, id2, ...]}` | +| `kanban_ideas` | `[Idea, ...]` | +| `kanban_ideas_seeded` | `'v3'` | + +--- + +## Default-Boards + +| ID | Name | Gruppe | Ring | +|---|---|---|---| +| ringsystem | Ringsystem | Meta | 0 | +| kanban | Kanban (dieses Board) | Meta | 0 | +| doener | Döner-App | Code | 3 | +| musichub | Music Hub | Code | 1w | +| openclaw | OpenClaw / Rob | Code | 1w | +| docpilot | docpilot | Code | 1w | +| k4 | K4 Digital — PM-Mandat | Beruflich | 1w | +| branding | Branding & Außendarstellung | Beruflich | 1w | +| psk | PSK I Zertifizierung | Beruflich | 1w | +| eu | Einzelunternehmen | Beruflich | 1w | +| pleasance | Pleasance | Web | 3 | +| mdim | mydrugismusic Website | Web | 3 | +| privat | Haushalt & Leben | Privat | 1p | +| degoogle | De-Google / FOSS Migration | Privat | 1p | +| bibliothek | Bibliothek-Pipeline | Privat | 1p | +| aikb | AI Engineering KB | Privat | 1w | + +**Overview gefüllt für:** doener, kanban, ringsystem. Andere: nur Skeleton (Pilot-Modus). + +--- + +## Tool-Agnostik + +| Datei | Status | +|---|---| +| `~/.claude/AGENTS.md` | kanonisch | +| `~/.claude/CLAUDE.md` | Symlink → AGENTS.md | +| `~/dev/personal-vault/AGENTS.md` | kanonisch | +| `~/dev/personal-vault/CLAUDE.md` | Symlink → AGENTS.md | +| `~/dev/robin-work/AGENTS.md` | kanonisch | +| `~/dev/robin-work/CLAUDE.md` | Symlink → AGENTS.md | + +**Backup:** `~/.claude/CLAUDE.md.bak` (alte Datei vor der Symlink-Migration) + +Skills tool-agnostisch über `~/.skills/{name}.md` mit Symlinks aus tool-spezifischen Verzeichnissen (Claude: `~/.claude/skills/{name}/SKILL.md`; OpenCode: `~/.config/opencode/commands/{name}.md`). + +--- + +## Local-Server + +``` +~/dev/kanban/server.sh +``` + +Startet `python3 -m http.server 8765 --bind 127.0.0.1` aus `~/`. + +- Aufruf: `~/dev/kanban/server.sh` (Vordergrund) oder `nohup ~/dev/kanban/server.sh &` (Hintergrund persist) +- Stop: `pkill -f "http.server 8765"` +- Logs: `/tmp/kanban-server.log` (wenn via nohup gestartet) + +Benötigt nur für **MD-Viewer** und localhost-URLs. Board-Funktion funktioniert auch ohne Server unter `file://`. Aber dann erscheint ein Warn-Banner oben. + +--- + +## MD-Viewer + +Klick auf Launch-Card mit `.md`-URL → Modal mit gerendertem Markdown. + +Mini-Parser inline: Headings (h1-h3), Bold, Italic, inline Code, Code-Blocks, Listen (ul/ol), Tables, Blockquotes, Hr, Links. + +Fallback wenn `fetch()` scheitert (CORS): Anleitung mit drei Optionen (Extension / Server / Tab). + +--- + +## Wichtige JS-Funktionen + +### Render +| Funktion | Beschreibung | +|---|---| +| `show(id)` | Board wechseln | +| `setView(v)` | Tab-Switch (overview/board/analytics) | +| `renderOverview(id)` | Hero + 5 Sektionen | +| `renderBoard(id)` | Swimlane + 3 Spalten + col-add-input | +| `renderAnalytics(id)` | KPIs, Flow, Monte Carlo, Blockers, SLE | +| `renderSidebar()` | Gruppen + Boards | +| `renderIdeas()` | gefilterte Ideen mit Drag-Attrs | +| `initBadges()` | Alias renderSidebar | +| `renderMarkdown(src)` | Mini-MD-Parser | + +### State +| Funktion | Beschreibung | +|---|---| +| `loadState()` / `saveState()` | BOARDS persist mit Override-Logik für Defaults | +| `loadGroups()` / `saveGroups()` | + Migration: `Meta` vorne einfügen wenn fehlend | +| `loadBoardOrder()` / `saveBoardOrder()` | per-Group-Order | +| `loadIdeas()` / `saveIdeas()` | + Seeding | +| `migrateCols(b)` | 5→3-Spalten-Migration | +| `getBoardsForGroup(g)` | geordnete Board-IDs | + +### Mutations (Board) +| Funktion | Beschreibung | +|---|---| +| `addCard(boardId, colId, text)` | mit `movedAt` + ggf. `doneAt` | +| `deleteCard(boardId, colId, idx)` | | +| `toggleBlocker(boardId, colId, idx)` | `task.blocked` | +| `saveBoardSetting(key, el, min, max)` | wipLimit/throughput/sleDays | +| `saveBoardName()` / `saveBoardGoal()` | Header-Edit | +| `saveFocus()` | Fokus-Text im Header | +| `resetCurrentBoard()` | Default-Reset oder User-Board-Delete | +| `deleteBoard(id, e)` | nur user-erstellt | +| `cycleRing(boardId, e)` | togglet durch Ring-Werte | +| `promoteToBoard(boardId, colId, idx)` | Task → neues Board | + +### Mutations (Overview) +| Funktion | Beschreibung | +|---|---| +| `updateOvFromEl(el)` | aus data-section/idx/prop | +| `addOvRow(section)` | leere Zeile für info/secrets/launches/commands | +| `addOvPill(section, value)` | für stack | +| `deleteOvRow(section, idx)` | | +| `enableEdit(el)` | Launch-Card-Felder Doppelklick aktiviert | +| `toggleSecretBtn(btn)` | masked toggle | +| `copyText(t, btn)` / `copyFromBtn(btn)` | Clipboard mit visual feedback | + +### Mutations (Ideen) +| Funktion | Beschreibung | +|---|---| +| `addIdea()` / `deleteIdea(idx)` | | +| `filterIdeas(tag)` | + setzt Default-Tag | +| `openPromote(idx)` / `confirmPromote()` / `closePromote()` | Modal Idee→Task | + +### Add-Board-Modal +| Funktion | Beschreibung | +|---|---| +| `showAddBoard()` / `closeAddBoard()` | | +| `selectAbColor(c, el)` | Farb-Picker | +| `confirmAddBoard()` | + Promote-Source-Handling | +| `showAddGroup()` | prompt()-Dialog | + +### DnD +| Funktion | Beschreibung | +|---|---| +| `onDragStart/End` (Cards) | + `showIdeaDropZones(on)` | +| `onDragOver/Drop` (col-body) | demotet expedite, handelt auch Ideen-Drops | +| `onDragOverExp/onDropToExpCol` | promoted expedite | +| `onBoardDragStart/End` | Board-Drag in Sidebar | +| `onGroupDragOver/Drop` | Board → Gruppe | +| `onNavItemDragOver/Drop` | Board-Reorder innerhalb Gruppe | +| `onIdeaDragStart/End` | Idee aus Pinnwand | +| `onGroupHeaderDragStart/End` | Gruppe-Reorder | +| `onGroupSectionDragOver/Drop` | Gruppe-Drop-Target | +| `onIdeaZoneDragOver` / `onDropToIdeas` | Card → Idee | +| `onLaunchClick(e, card)` | Launch-Card öffnet URL/MD | + +### Helper +| Funktion | Beschreibung | +|---|---| +| `escapeHtml(s)` | HTML-Escape | +| `liveAge(task)` | aus `movedAt` | +| `ageClass(days)` | fresh/ok/warn/old | +| `colCount(b, id)` | tasks.length | +| `remaining(b)` | ready + wip | +| `hasBlocker(b)` | any task.blocked | +| `monteCarlo(left, tp, runs)` | {p50,p75,p85,p95} | +| `realThroughput(b, days)` | aus Done-History | +| `openMD(url)` / `closeMD()` / `openMdExternal()` | MD-Viewer | +| `enableEdit(el)` | Launch-Card-Edit-Modus aktivieren | + +### Globals +```js +let curId = 'doener'; +let curView = 'overview'; // default +let BOARDS = {}; // runtime, mutiert +let IDEAS = []; +let GROUPS = ['Meta','Code',...]; +let BOARD_ORDER = {}; +let dragSrc = null; // {boardId, colId, idx} bei Card-Drag im Board +let dragBoard = null; // boardId bei Sidebar-Drag +let dragIdea = null; // idx bei Ideen-Drag +let dragGroup = null; // group bei Gruppe-Drag +let promoteSource = null; // {boardId, colId, idx} beim Task→Board +let abSelColor = '#7c6af7'; +let promoteIdx = null; +let mdCurrentUrl = null; +``` + +--- + +## CSS-Variablen (Theme) + +``` +--bg:#0d0d0f, --surface:#16161a, --surface2:#1e1e24, --surface3:#26262e +--border:#2a2a35, --border2:#353545 +--text:#e8e8f0, --text-muted:#6b6b80, --text-dim:#4a4a5a +--accent:#7c6af7 (lila), --accent-soft:#2d2550 +--green:#4ade80, --amber:#fbbf24, --red:#f87171, --blue:#60a5fa +--teal:#2dd4bf, --purple:#c084fc, --orange:#fb923c +--sidebar-w:210px, --col-w:240px +``` + +Color-of-State Konvention: +- **Ready** = amber +- **In Progress** = blau +- **Done** = grün +- **Blocked** = rot (Border + Background-Tint) +- **Expedite** = rot (border-left + Swimlane-Background) +- **Fixed Date** = amber (border-left) +- **Aging > SLE** = roter Glow + +--- + +## Test-Checkliste (für externe Tester-Agents) + +### Layout & Navigation +- [ ] Sidebar links: alle 5 Gruppen sichtbar (Meta · Code · Beruflich · Web · Privat) +- [ ] Meta-Gruppe: lila Gradient mit `◉`-Bullet +- [ ] Klick auf jedes Board lädt korrektes Layout, Header zeigt Name, Goal, Pills (WIP-Limit/TP/SLE), Fokus-Stern +- [ ] Tab-Reihenfolge: Overview · Board · Analytics +- [ ] Default-Tab beim Start: Overview +- [ ] Banner oben wenn auf `file://` (nicht localhost:8765) + +### Boards +- [ ] `+ Board` öffnet Modal mit Name (Pflicht), Goal, Gruppe-Select (+ "Neue Gruppe…"), Farb-Picker (8 Farben) +- [ ] User-Board zeigt `×` bei Hover (Default-Boards nicht) +- [ ] `+ Gruppe` legt leere Gruppe an (sichtbar mit "Leer — Board hinzufügen" Placeholder) +- [ ] Board-Drag in andere Gruppe → Group-Wechsel persistent +- [ ] Board-Drag auf konkretes Nav-Item → Reihenfolge innerhalb Gruppe persistent +- [ ] Gruppe-Header draggable → Gruppen-Reihenfolge ändert +- [ ] Ring-Badge (R0/R1p/R1w/R2/R3) togglet bei Klick durch alle Werte +- [ ] `↺ Reset`: bei Default-Board Spalten reset, bei User-Board Löschen-Confirm +- [ ] Board-Name + Goal per Klick im Header editierbar (Enter speichert, Esc revert) + +### Settings (Pills im Header) +- [ ] WIP-Limit Pill editierbar (1-20) +- [ ] Throughput Pill editierbar (0.5-30, Dezimalen erlaubt) +- [ ] SLE-Tage Pill editierbar (1-180) +- [ ] Alle drei persistent nach Reload + +### Karten (Board-View) +- [ ] `+ Karte…` Input: Enter fügt hinzu, Esc blurt +- [ ] Hover-Buttons: ⚑ togglet blocked (Karte rot), ↗ öffnet Promote-Modal, × löscht +- [ ] Drag col-body → col-body: verschiebt + setzt `movedAt` +- [ ] Drag col-body → exp-zone: verschiebt + setzt cos=expedite +- [ ] Drag exp-zone → exp-zone: verschiebt + bleibt expedite +- [ ] Drag exp-zone → col-body: demotet (cos entfernt) +- [ ] Drag in `done` setzt zusätzlich `doneAt` +- [ ] Karte > SLE-Tage in Spalte (außer done): rot leuchtender Glow + "ÜBERFÄLLIG"-Label +- [ ] Drag Card → eine der vier Ideen-Drop-Zonen (rechte Sidebar): erstellt Idee, entfernt Card + +### Promote-to-Board +- [ ] ↗ auf Karte öffnet Modal mit Name = Task-Titel +- [ ] Hint zeigt Quell-Board und -Spalte korrekt +- [ ] Gruppe + Farbe vorbelegt mit Quell-Board +- [ ] Confirm → neues User-Board, Task aus Quelle entfernt +- [ ] Cancel → kein Board angelegt, Quell-Task bleibt + +### Overview +- [ ] Hero-Block: Icon (oder Emoji-Fallback in Board-Farbe), Name, Tagline, Description, Badge-Reihe (Ring/Gruppe/Typ) +- [ ] Tagline + Description + Type per Single-Click editierbar (Click + tippen) +- [ ] Launch-Cards: **Single-Click öffnet URL** (oder MD-Viewer bei .md-URL); **Doppelklick auf Text aktiviert Edit-Modus** +- [ ] `× Entfernen` löscht Launch-Card +- [ ] `+ Launch-Card` fügt leere Card hinzu +- [ ] Was bisher geschah: per Click editierbar +- [ ] Tech-Stack-Pills: `×` löscht, `+ Tech` Input fügt hinzu +- [ ] Info-Rows: Label + Value editierbar, Copy-Btn (✓ Feedback), `×` löscht, `+ Zeile` fügt hinzu +- [ ] Secrets: Label + Value editierbar, Auge-Toggle (masked persistent), Copy-Btn, `×`, `+ Secret` +- [ ] Quick-Commands: Label + Cmd editierbar, Copy-Btn, `×`, `+ Command` + +### MD-Viewer +- [ ] Voraussetzung: Aufruf via `http://localhost:8765/dev/kanban/index.html` (Server läuft) +- [ ] Klick auf `.md`-Launch-Card öffnet Modal mit gerendertem Markdown (Headings, Code, Tables, Listen) +- [ ] `↗ Tab` öffnet Roh-Inhalt in neuer Tab +- [ ] `× Schließen` oder Klick auf Overlay schließt Modal +- [ ] Bei `file://`-Aufruf: Fallback-Anleitung erscheint mit drei Optionen + +### Analytics +- [ ] Tab-Wechsel ohne State-Verlust +- [ ] WIP-KPI färbt rot bei `> wipLimit`, amber bei `= wipLimit`, blau sonst +- [ ] Cycle Time, Queue ETA, Flow Efficiency mathematisch plausibel (siehe Spec oben) +- [ ] Monte Carlo Throughput-Input updated Live +- [ ] Status-Pill grün "↻ Real" wenn Done-Cards mit doneAt < 14d existieren, sonst grau "⊘ Statisch" +- [ ] Active Blockers Panel listet alle Tasks mit `blocked:true` +- [ ] Flow Distribution: 3 Balken (Ready/WIP/Done) korrekt skaliert + +### Ideen +- [ ] Input + Enter fügt Idee am Anfang ein +- [ ] Filter-Buttons: ändern Anzeige UND Default-Tag für neue Ideen +- [ ] Hover-Buttons: `→` Promote-Modal (Spalten-Default = erste verfügbare, nie 'backlog'), `✕` löscht +- [ ] Drag Idee in col-body → Task entsteht, Idee verschwindet +- [ ] Drag funktioniert nur auf col-body, nicht in exp-zone + +### Persistenz +- [ ] Reload behält: Boards, Spalten-States, Fokus, Ideen, Gruppen, Group-Order, alle Overrides (name/goal/wipLimit/tp/sle/overview) +- [ ] `localStorage.clear()` + Reload → alle Defaults zurück inkl. Seed-Ideen v3 +- [ ] Alte 5-Spalten-States werden via `migrateCols` zu 3-Spalten konsolidiert + +### Tool-Agnostik +- [ ] `~/.claude/CLAUDE.md` ist Symlink auf `AGENTS.md` +- [ ] `~/.claude/CLAUDE.md.bak` enthält den alten Inhalt vor Migration +- [ ] Ringsystem-Board zeigt alle relevanten MD-Files als Launch-Cards mit korrekten http://localhost:8765-URLs + +--- + +## Bekannte Einschränkungen + +- Karten-Sortierung INNERHALB einer Spalte nicht möglich (immer append) +- Card-Edit (Titel/Note ändern) nicht möglich — nur löschen + neu +- Gruppen können nicht umbenannt oder gelöscht werden +- Kein Card-Detail-View (kein Comments, Attachments, History) +- Kein Export +- Keine Tastatur-Shortcuts +- localStorage nicht synchronisiert — pro Browser/Gerät separat +- Keine Undo-Funktion +- CFD-Chart noch nicht implementiert (Ready-Task) +- Throughput-History akkumuliert sich erst über Zeit — bei frischem Start fallback auf statischen Wert + +--- + +## Datei-Struktur + +``` +/Users/robinchoice/dev/kanban/ +├── index.html # Die gesamte App +├── SPEC.md # Diese Datei +├── server.sh # Local HTTP Server (chmod +x) +└── assets/ + └── doener.png # App-Icon (kopiert aus ~/dev/doener-app/iOS/.../AppIcon.appiconset/icon-1024.png) +``` + +--- + +## Setup (für neue Session / anderen Agent) + +```bash +# 1. Server starten (für MD-Viewer) +nohup ~/dev/kanban/server.sh > /tmp/kanban-server.log 2>&1 & + +# 2. Im Browser öffnen +open http://localhost:8765/dev/kanban/index.html + +# 3. Stop wenn nötig +pkill -f "http.server 8765" +``` + +Wenn Server nicht laufen soll: einfach `open ~/dev/kanban/index.html` — Board funktioniert, aber MD-Viewer-Modal zeigt Fallback-Anleitung statt gerenderter Inhalte. diff --git a/assets/doener.png b/assets/doener.png new file mode 100644 index 0000000..4b02811 Binary files /dev/null and b/assets/doener.png differ diff --git a/index.html b/index.html new file mode 100644 index 0000000..bcd4d3d --- /dev/null +++ b/index.html @@ -0,0 +1,2331 @@ + + + + + +Robin — Projects + + + + + + + + +
+
+
+
+
+
+ + Fokus +
+
+
+
+
Overview
+
Board
+
Analytics
+
+
+
+
+
+ + + + + +
+
+
+
+
+ + +
+
+
+
+
+ + + + + + diff --git a/server.sh b/server.sh new file mode 100755 index 0000000..56ef165 --- /dev/null +++ b/server.sh @@ -0,0 +1,19 @@ +#!/bin/bash +# Kanban Local Server +# +# Static-File-Server aus dem Home-Verzeichnis. Damit funktionieren +# der eingebaute MD-Viewer und alle file://-Referenzen ohne CORS-Probleme. +# +# Aufruf: +# ~/dev/kanban/server.sh # läuft im Vordergrund +# ~/dev/kanban/server.sh & # Hintergrund (nohup für persist nach Logout) +# pkill -f "http.server 8765" # zum Beenden +# +# Kanban dann öffnen unter: http://localhost:8765/dev/kanban/index.html +# (Backwards-Compat: http://localhost:8765/.kanban/index.html funktioniert über Symlink) + +set -e +cd ~ +echo "Kanban-Server läuft auf http://localhost:8765/dev/kanban/index.html" +echo "Stop: Ctrl-C · Hintergrund: ~/dev/kanban/server.sh &" +exec python3 -m http.server 8765 --bind 127.0.0.1