diff --git a/CLAUDE.md b/CLAUDE.md index 4ca02c1..81338e5 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -137,7 +137,19 @@ source .venv/bin/activate && pip install -r requirements.txt **Memory** (`src/memory_search.py`): Embeddings Ollama all-minilm (384 dim) + cosine similarity SQLite. Trăiește la `memory/` în acest repo — single source of truth. *Notă istorică:* era symlink la repo-ul legacy Clawdbot; consolidat în echo-core în migrația OpenClaw (2026-04). -**Dashboard** (`dashboard/`): Echo Task Board — HTTP API + UI static servit de `dashboard/api.py` pe portul 8088, de obicei în spatele unui reverse proxy la `/echo/`. Logica endpoint-urilor împărțită în mixin-uri `dashboard/handlers/*.py`; path-urile centralizate în `dashboard/constants.py`. Template systemd user unit la `dashboard/echo-taskboard.service`. +**Dashboard** (`dashboard/`): Echo Task Board — HTTP API + UI static servit de `dashboard/api.py` pe portul 8088, de obicei în spatele unui reverse proxy la `/echo/`. Logica endpoint-urilor împărțită în mixin-uri `dashboard/handlers/*.py`; path-urile centralizate în `dashboard/constants.py`. Template systemd user unit la `dashboard/echo-taskboard.service`. `workspace.html` este hub-ul unificat de proiecte (fostul ralph.html + workspace.html); `/echo/ralph.html` → 302 redirect la `/echo/workspace.html`. Autentificare prin cookie httpOnly `dashboard=`; `DASHBOARD_TOKEN` setat în `dashboard/.env`. + +## Dashboard — Note arhitecturale + +**Cookie auth:** dashboard folosește httpOnly cookie `dashboard=...`; SameSite=Strict; Path=/echo/. EventSource SSE trimite cookie-ul automat. `DASHBOARD_TOKEN` din `dashboard/.env` — setează o dată, restart service. Resetare: schimbă valoarea din .env + restart. + +**jsonlock helper (`src/jsonlock.py`):** folosește `read_locked(path)` / `write_locked(path, mutator)` pentru orice scriere la `approved-tasks.json`, `sessions/*.json`. Lock pe sidecar `.lock` (inode stabil chiar și după os.replace). Ordine canonică lock-uri: alfabetic după filename. Re-entrant (threading.local refcount). + +**Slug convention:** slug-urile proiectelor validează cu regex `^[a-z0-9][a-z0-9\-_]{1,38}[a-z0-9]$` — permit hifene ȘI underscore. Validare centralizată în `dashboard/handlers/_validators.py`. + +**Proxy timeout:** pentru nginx/caddy, setează `proxy_read_timeout >= 60s` și `proxy_buffering off` pentru `/echo/api/projects/stream` și `/echo/api/projects//plan/*` (SSE + planning au răspunsuri lungi). + +**Planning fragmentation (known limit):** sesiunile de planning pornite din Discord/Telegram nu se fuzionează cu cele din dashboard. Dashboard afișează sesiunea cea mai recentă per slug indiferent de adapter. P3 follow-up. ## Ralph — Execuție autonomă de proiecte @@ -151,7 +163,7 @@ Marius → /a (Discord/Telegram/WhatsApp → router.py → statu 23:00 night-execute → citește approved, clonează repo dacă lipsește, generează PRD din final-plan.md, lansează ralph.sh; actualizează approved-tasks.json (running, pid: PID) 08:30 morning-report → citește approved-tasks.json + prd.json per proiect, raportează stories done/total -Live dashboard → /echo/ralph.html (polling 5s) — cards per proiect cu status, iter, ETA, log, stop +Live dashboard → /echo/workspace.html — cards per proiect cu status, iter, ETA, log, stop; realtime SSE ``` **Două căi de aprobare**: @@ -203,8 +215,9 @@ Pe **WhatsApp**: text-only — meniu redirect la Discord/Telegram. **Text-keywor | `~/workspace//scripts/ralph/prd.json` | PRD per proiect cu schema extinsă | | `~/workspace//scripts/ralph/logs/` | Loguri ralph.sh per rulare | | `dashboard/handlers/ralph.py` | Endpoints `/api/ralph/status`, `//log`, `//prd`, `//stop`, `//rollback`, `/usage[?days=N]`, `/stream` (SSE) | -| `dashboard/ralph.html` | UI live cards, status badges, ETA, butoane log/prd/stop/rollback. Realtime via EventSource cu fallback la polling 5s; badge 🟢 Live / ⏱ Polling | -| `dashboard/.env` | `GITEA_TOKEN` pentru clone HTTPS la `gitea.romfast.ro` | +| `dashboard/handlers/projects.py` | Endpoints unificate proiecte: `/api/projects`, `/propose`, `/approve`, `/unapprove`, `/cancel`, `//plan/*`, `/stream` (SSE), `/signature` | +| `dashboard/workspace.html` | Hub unificat proiecte — cards status/iter/ETA, log, prd, stop/rollback. Realtime SSE cu fallback polling 5s. Înlocuiește ralph.html (care face 302 redirect aici) | +| `dashboard/.env` | `GITEA_TOKEN` pentru clone HTTPS la `gitea.romfast.ro`; `DASHBOARD_TOKEN` pentru cookie auth | **Status flow:** `pending` → (`planning` →) `approved` → `running` → `complete` / `failed` / `stopped` / `blocked` (DAG) **Story status (în prd.json):** `passes:false` + `retries:N` → `passes:true` SAU `failed:rate_limited|max_retries` @@ -234,9 +247,16 @@ Import-uri absolute via `sys.path.insert(0, PROJECT_ROOT)`: `from src.config imp | `personality/*.md` | System prompt — cine ești | | `memory/` | Knowledge base — embeddings + SQLite (în repo, nu symlink) | | `dashboard/api.py` | Task Board HTTP API (port 8088) | -| `dashboard/handlers/` | Mixin-uri endpoints (git, cron, habits, eco, files, pdf, workspace, youtube) | +| `dashboard/handlers/` | Mixin-uri endpoints (git, cron, habits, eco, files, pdf, workspace, youtube, projects, ralph, auth) | +| `dashboard/handlers/projects.py` | Endpoints unificate proiecte: `/api/projects`, `/propose`, `/approve`, `/unapprove`, `/cancel`, `//plan/*`, `/stream` (SSE) | +| `dashboard/handlers/auth.py` | Login/logout cu cookie httpOnly `dashboard=`; `DASHBOARD_TOKEN` din `.env` | +| `dashboard/handlers/_validators.py` | Validatori slug/descriere partajați. Slug regex: `^[a-z0-9][a-z0-9\-_]{1,38}[a-z0-9]$` (permite hifene ȘI underscore) | +| `dashboard/static/tokens.css` | Design tokens CSS (`--color-*`, `--space-*`, etc.) — shared variables pentru toate paginile | +| `dashboard/DESIGN.md` | Design system source-of-truth: tokens, componente, regula no-emoji | | `dashboard/constants.py` | Path-uri centralizate + config Gitea pentru dashboard | | `dashboard/echo-taskboard.service` | Template systemd user unit | +| `src/jsonlock.py` | Flock helper pentru scrieri concurente: `read_locked(path)`, `write_locked(path, mutator)`, `LockTimeoutError`. Sidecar `.lock` (inode stabil). Re-entrant per thread. Ordine canonică: alfabetic | +| `src/approved_tasks_cli.py` | CLI wrapper pentru shell scripts: scrie în `approved-tasks.json` prin jsonlock. Usage: `python3 -m src.approved_tasks_cli set-status --slug X --status Y` | | `cron/jobs.json` | Job-uri APScheduler (schemă plată, Europe/Bucharest) | | `approved-tasks.json` | Fișier coordonare Ralph — status proiecte autonome (extins cu `planning_session_id`, `final_plan_path`) | | `tasks/lessons.md` | Lecții capturate din corectările lui Marius (citit la session start) | diff --git a/cron/jobs.json b/cron/jobs.json index c4d51de..cc22ede 100644 --- a/cron/jobs.json +++ b/cron/jobs.json @@ -195,7 +195,7 @@ "channel": "echo-work", "model": "sonnet", "enabled": true, - "prompt": "RAPORT SEARĂ - trimite pe EMAIL (Gmail: mmarius28@gmail.com)\n\n## CALENDAR\nVerifică ce ai mâine și săptămâna:\n```bash\ncd ~/echo-core && source venv/bin/activate && python3 tools/calendar_check.py today\npython3 tools/calendar_check.py week\n```\n\n## CITEȘTE CONTEXT\n- USER.md pentru programul lui Marius (luni-joi 15-16 liber, vineri-dum NLP)\n- memory/kb/insights/YYYY-MM-DD.md pentru propuneri insights\n- memory/kb/youtube/ și memory/kb/articole/ pentru inspirație proiecte\n- /home/moltbot/echo-core/approved-tasks.json pentru status proiecte existente (câmpurile: name, status, proposed_at)\n\n## FORMAT EMAIL HTML\n- Font: 16px text, 18px titluri\n- Culori: albastru (#dbeafe) DONE, gri (#f3f4f6) PROGRAMAT, verde (#d1fae5) PROJECTS\n- Link-uri vizibile\n\n## STRUCTURA RAPORT\n\n### 1. MÂINE\n- 📅 Evenimente calendar\n- 🚂 Travel reminders\n\n### 2. STATUS\n- Ce s-a făcut azi\n- Git status\n\n### 3. PROPUNERI CU ZI ȘI ORĂ!\n\n**OBLIGATORIU:** Fiecare propunere TU+EU sau FAC TU trebuie să aibă ZI și ORĂ concrete!\n\nReguli programare:\n- Luni-Joi 15:00-16:00 = slot liber\n- Vineri-Duminică = NLP, evită\n- Verifică calendar să nu fie ocupat\n- Sesiuni scurte: 15-30 min\n\n### 4. PROGRAME/PROIECTE PRACTICE 💻\n\n**CONTEXT OBLIGATORIU - citește înainte de a propune:**\n\n**Proiecte existente (PRIORITARE pentru features):**\n- **roa2web** (gitea.romfast.ro/romfast/roa2web) - FastAPI+Vue.js+Telegram bot\n - Are deja: balanță, facturi, trezorerie\n - Lipsesc: validări declarații ANAF, facturare valută/taxare inversă, notificări\n - Rapoarte ROA noi → FEATURE în roa2web, NU proiect separat!\n- **Chatbot Maria** (Flowise pe LXC 104, ngrok → romfast.ro/chatbot_maria.html)\n - Document store: XML, MD | Groq gratuit + Ollama embeddings + FAISS\n - Problema: răspunsuri nu sunt suficient de bune\n - Angajatul nou poate menține documentația (scrie TXT, trebuie converter)\n - Clientii îl accesează din programele ROA direct\n\n**Întrebări frecvente clienți (surse de proiecte):**\n- Erori validare declarații ANAF (D406, D394, D100 etc.)\n- Cum facturez în valută cu taxare inversă?\n- Probleme la instalări, inițializări firme noi, configurări\n\n**Reguli propuneri (80/20 STRICT):**\n- Impact mare pentru Marius → apoi pentru clienți ERP ROA\n- Inspirat din discovery (YouTube, articole, insights procesate)\n- Features roa2web > proiecte noi (integrare în existent)\n- Proiecte independente doar dacă NU se potrivesc în roa2web/Flowise\n\n**A. FEATURES PROIECTE EXISTENTE (2-3, PRIORITAR):**\n\nFormat:\n```\n### ⚡ F1 - Feature pentru [roa2web/chatbot]\n**Ce face:** Descriere scurtă\n**De ce:** Ce problemă rezolvă (ex: \"clienții întreabă X de 5 ori/săptămână\")\n**Complexitate:** S/M/L\n**Proiect:** roa2web / chatbot-maria\n```\n\n**B. PROIECTE NOI (max 1, doar dacă nu se integrează în existente):**\n\nFormat:\n```\n### 💻 P1 - Nume Proiect\n**De ce:** Cum se leagă de nevoile lui Marius/clienți\n**Impact:** Pentru Marius + pentru clienți\n**Efort:** Ore/zile realist\n**Stack:** Simplu (80/20)\n**Sursă:** [Link nota KB]\n```\n\n**NU propune:**\n- Proiecte complexe fără beneficiu clar\n- Proiecte duplicat cu ce există deja\n- Rapoarte ROA ca proiect separat (→ feature roa2web)\n\n### 5. INSIGHTS DISPONIBILE\nListează insights-uri [ ] nepropuse încă (format scurt).\n\n### 6. CUM RĂSPUNZI\n- DA = aprob toate (cu zilele/orele propuse)\n- 1 pentru A1,A2 = execut ACUM\n- 2 pentru A3 = programez noapte\n- 3 pentru A5 = skip\n- **F pentru F1,F3** = implementează features (joburi noapte)\n- **P pentru P1** = creează proiect nou (job noapte)\n- Alt orar = \"A1 miercuri nu marți\"\n\n## IMPLEMENTARE PROIECTE APROBATE\n\nCând propui features (F) sau proiecte (P), adaugă-le automat în /home/moltbot/echo-core/approved-tasks.json cu status 'pending':\n```bash\npython3 -c \"\nimport json, datetime\nf = open('/home/moltbot/echo-core/approved-tasks.json')\ndata = json.load(f); f.close()\ndata['projects'].append({'name': 'SLUG-PROIECT', 'description': 'DESCRIERE', 'status': 'pending', 'proposed_at': datetime.datetime.utcnow().isoformat(), 'approved_at': None, 'started_at': None, 'pid': None})\ndata['last_updated'] = datetime.datetime.utcnow().isoformat()\nopen('/home/moltbot/echo-core/approved-tasks.json', 'w').write(json.dumps(data, indent=2))\n\"\n```\n\nÎn email, arată lui Marius comanda de aprobare:\n`!approve SLUG-PROIECT` (trimite pe Discord/Telegram la Echo)\n\nNight-execute (23:00) va:\n - genera PRD cu ralph_prd_generator.py dacă nu există prd.json\n - lansa ralph.sh 15 iterații pentru fiecare proiect aprobat\n\n## TRIMITERE\npython3 /home/moltbot/echo-core/tools/email_send.py \"mmarius28@gmail.com\" \"Raport Seara DATA\" \"HTML_CONTENT\"\n\nNU trimite pe Discord - doar email.", + "prompt": "RAPORT SEARĂ - trimite pe EMAIL (Gmail: mmarius28@gmail.com)\n\n## CALENDAR\nVerifică ce ai mâine și săptămâna:\n```bash\ncd ~/echo-core && source venv/bin/activate && python3 tools/calendar_check.py today\npython3 tools/calendar_check.py week\n```\n\n## CITEȘTE CONTEXT\n- USER.md pentru programul lui Marius (luni-joi 15-16 liber, vineri-dum NLP)\n- memory/kb/insights/YYYY-MM-DD.md pentru propuneri insights\n- memory/kb/youtube/ și memory/kb/articole/ pentru inspirație proiecte\n- /home/moltbot/echo-core/approved-tasks.json pentru status proiecte existente (câmpurile: name, status, proposed_at)\n\n## FORMAT EMAIL HTML\n- Font: 16px text, 18px titluri\n- Culori: albastru (#dbeafe) DONE, gri (#f3f4f6) PROGRAMAT, verde (#d1fae5) PROJECTS\n- Link-uri vizibile\n\n## STRUCTURA RAPORT\n\n### 1. MÂINE\n- 📅 Evenimente calendar\n- 🚂 Travel reminders\n\n### 2. STATUS\n- Ce s-a făcut azi\n- Git status\n\n### 3. PROPUNERI CU ZI ȘI ORĂ!\n\n**OBLIGATORIU:** Fiecare propunere TU+EU sau FAC TU trebuie să aibă ZI și ORĂ concrete!\n\nReguli programare:\n- Luni-Joi 15:00-16:00 = slot liber\n- Vineri-Duminică = NLP, evită\n- Verifică calendar să nu fie ocupat\n- Sesiuni scurte: 15-30 min\n\n### 4. PROGRAME/PROIECTE PRACTICE 💻\n\n**CONTEXT OBLIGATORIU - citește înainte de a propune:**\n\n**Proiecte existente (PRIORITARE pentru features):**\n- **roa2web** (gitea.romfast.ro/romfast/roa2web) - FastAPI+Vue.js+Telegram bot\n - Are deja: balanță, facturi, trezorerie\n - Lipsesc: validări declarații ANAF, facturare valută/taxare inversă, notificări\n - Rapoarte ROA noi → FEATURE în roa2web, NU proiect separat!\n- **Chatbot Maria** (Flowise pe LXC 104, ngrok → romfast.ro/chatbot_maria.html)\n - Document store: XML, MD | Groq gratuit + Ollama embeddings + FAISS\n - Problema: răspunsuri nu sunt suficient de bune\n - Angajatul nou poate menține documentația (scrie TXT, trebuie converter)\n - Clientii îl accesează din programele ROA direct\n\n**Întrebări frecvente clienți (surse de proiecte):**\n- Erori validare declarații ANAF (D406, D394, D100 etc.)\n- Cum facturez în valută cu taxare inversă?\n- Probleme la instalări, inițializări firme noi, configurări\n\n**Reguli propuneri (80/20 STRICT):**\n- Impact mare pentru Marius → apoi pentru clienți ERP ROA\n- Inspirat din discovery (YouTube, articole, insights procesate)\n- Features roa2web > proiecte noi (integrare în existent)\n- Proiecte independente doar dacă NU se potrivesc în roa2web/Flowise\n\n**A. FEATURES PROIECTE EXISTENTE (2-3, PRIORITAR):**\n\nFormat:\n```\n### ⚡ F1 - Feature pentru [roa2web/chatbot]\n**Ce face:** Descriere scurtă\n**De ce:** Ce problemă rezolvă (ex: \"clienții întreabă X de 5 ori/săptămână\")\n**Complexitate:** S/M/L\n**Proiect:** roa2web / chatbot-maria\n```\n\n**B. PROIECTE NOI (max 1, doar dacă nu se integrează în existente):**\n\nFormat:\n```\n### 💻 P1 - Nume Proiect\n**De ce:** Cum se leagă de nevoile lui Marius/clienți\n**Impact:** Pentru Marius + pentru clienți\n**Efort:** Ore/zile realist\n**Stack:** Simplu (80/20)\n**Sursă:** [Link nota KB]\n```\n\n**NU propune:**\n- Proiecte complexe fără beneficiu clar\n- Proiecte duplicat cu ce există deja\n- Rapoarte ROA ca proiect separat (→ feature roa2web)\n\n### 5. INSIGHTS DISPONIBILE\nListează insights-uri [ ] nepropuse încă (format scurt).\n\n### 6. CUM RĂSPUNZI\n- DA = aprob toate (cu zilele/orele propuse)\n- 1 pentru A1,A2 = execut ACUM\n- 2 pentru A3 = programez noapte\n- 3 pentru A5 = skip\n- **F pentru F1,F3** = implementează features (joburi noapte)\n- **P pentru P1** = creează proiect nou (job noapte)\n- Alt orar = \"A1 miercuri nu marți\"\n\n## IMPLEMENTARE PROIECTE APROBATE\n\nCând propui features (F) sau proiecte (P), adaugă-le automat în /home/moltbot/echo-core/approved-tasks.json cu status 'pending'. Folosește CLI wrapper-ul (atomic, flock-safe — NU edita fișierul direct):\n```bash\ncd /home/moltbot/echo-core && source .venv/bin/activate && \\\n python3 -m src.approved_tasks_cli add-project \\\n --slug SLUG-PROIECT \\\n --description \"DESCRIERE COMPLETĂ\"\n```\n\nÎn email, arată lui Marius comanda de aprobare:\n`!approve SLUG-PROIECT` (trimite pe Discord/Telegram la Echo)\n\nNight-execute (23:00) va:\n - genera PRD cu ralph_prd_generator.py dacă nu există prd.json\n - lansa ralph.sh 15 iterații pentru fiecare proiect aprobat\n\n## TRIMITERE\npython3 /home/moltbot/echo-core/tools/email_send.py \"mmarius28@gmail.com\" \"Raport Seara DATA\" \"HTML_CONTENT\"\n\nNU trimite pe Discord - doar email.", "allowed_tools": [], "last_run": "2026-04-27T21:00:00.003134+00:00", "last_status": "ok", @@ -269,9 +269,9 @@ "prompt": "Heartbeat check. Rulează src/heartbeat.py printr-un scurt raport de status.\nDacă nu e nimic de raportat (email=0, calendar nu are evenimente <2h, kb ok), răspunde doar cu HEARTBEAT_OK și oprește-te — nu trimite mesaj.\nDacă e ceva: raport scurt pe Discord #echo-work.", "allowed_tools": [], "enabled": true, - "last_run": "2026-04-27T18:00:00.002242+00:00", + "last_run": "2026-04-28T06:00:00.001979+00:00", "last_status": "ok", - "next_run": "2026-04-28T06:00:00+00:00" + "next_run": "2026-04-28T08:00:00+00:00" }, { "name": "night-execute", @@ -279,7 +279,7 @@ "channel": "echo-work", "model": "opus", "enabled": true, - "prompt": "NIGHT-EXECUTE - Implementare autonoma proiecte aprobate\n\n## PASUL 1: Citeste proiectele aprobate\n\nCiteste /home/moltbot/echo-core/approved-tasks.json\nSelecteaza proiectele cu status='approved'\nDaca nu sunt proiecte aprobate: raporteaza pe Discord si opreste-te.\n\n## PASUL 2: Pentru fiecare proiect aprobat\n\n1. Verifica daca workspace-ul exista: /home/moltbot/workspace/{name}\n - Daca nu: TOKEN=$(grep GITEA_TOKEN /home/moltbot/echo-core/dashboard/.env | cut -d= -f2) && git clone https://moltbot:${TOKEN}@gitea.romfast.ro/romfast/{name}.git /home/moltbot/workspace/{name}\n\n2. Verifica daca prd.json exista: /home/moltbot/workspace/{name}/scripts/ralph/prd.json\n - Daca nu: ruleaza generatorul PRD:\n source .venv/bin/activate\n python3 tools/ralph_prd_generator.py \"{name}\" \"{description}\" /home/moltbot/workspace\n\n3. Lanseaza Ralph loop:\n cd /home/moltbot/workspace/{name}\n chmod +x scripts/ralph/ralph.sh\n mkdir -p scripts/ralph/logs\n nohup ./scripts/ralph/ralph.sh 15 > scripts/ralph/logs/ralph-$(date +%Y%m%d).log 2>&1 &\n echo $! > scripts/ralph/.ralph.pid\n\n4. Actualizeaza approved-tasks.json:\n - status: 'running'\n - started_at: timestamp curent\n - pid: PID din .ralph.pid\n\n## PASUL 3: Raport Discord\n\nTrimite pe echo-work:\n- Cate proiecte au pornit\n- PID-urile lor\n- 'morning-report va raporta progresul la 08:30'\n\n## REGULI IMPORTANTE\n\n- Nu modifica niciodata src/router.py, src/claude_session.py sau alte fisiere core echo-core prin Ralph\n- echo-core self-improvement NUMAI pe branch ralph/echo-improve, nu pe master\n- Daca ralph.sh esueaza: log in approved-tasks.json (status: failed, error: mesaj)\n- Delay 5 secunde intre proiecte pentru a evita rate limiting\n", + "prompt": "NIGHT-EXECUTE - Implementare autonoma proiecte aprobate\n\n## PASUL 1: Citeste proiectele aprobate\n\nCiteste /home/moltbot/echo-core/approved-tasks.json\nSelecteaza proiectele cu status='approved'\nDaca nu sunt proiecte aprobate: raporteaza pe Discord si opreste-te.\n\n## PASUL 2: Pentru fiecare proiect aprobat\n\n1. Verifica daca workspace-ul exista: /home/moltbot/workspace/{name}\n - Daca nu: TOKEN=$(grep GITEA_TOKEN /home/moltbot/echo-core/dashboard/.env | cut -d= -f2) && git clone https://moltbot:${TOKEN}@gitea.romfast.ro/romfast/{name}.git /home/moltbot/workspace/{name}\n\n2. Verifica daca prd.json exista: /home/moltbot/workspace/{name}/scripts/ralph/prd.json\n - Daca nu: ruleaza generatorul PRD:\n source .venv/bin/activate\n python3 tools/ralph_prd_generator.py \"{name}\" \"{description}\" /home/moltbot/workspace\n\n3. Lanseaza Ralph loop:\n cd /home/moltbot/workspace/{name}\n chmod +x scripts/ralph/ralph.sh\n mkdir -p scripts/ralph/logs\n nohup ./scripts/ralph/ralph.sh 15 > scripts/ralph/logs/ralph-$(date +%Y%m%d).log 2>&1 &\n echo $! > scripts/ralph/.ralph.pid\n\n4. Actualizeaza approved-tasks.json prin CLI wrapper-ul atomic (NU edita fisierul direct — foloseste flock):\n ```bash\n PID=$(cat /home/moltbot/workspace/{name}/scripts/ralph/.ralph.pid)\n cd /home/moltbot/echo-core && source .venv/bin/activate && \\\n python3 -m src.approved_tasks_cli mark-running --slug {name} --pid \"$PID\"\n ```\n (echivalent cu: status='running', started_at=now, pid=PID — toate intr-un singur write_locked)\n\n## PASUL 3: Raport Discord\n\nTrimite pe echo-work:\n- Cate proiecte au pornit\n- PID-urile lor\n- 'morning-report va raporta progresul la 08:30'\n\n## REGULI IMPORTANTE\n\n- Nu modifica niciodata src/router.py, src/claude_session.py sau alte fisiere core echo-core prin Ralph\n- echo-core self-improvement NUMAI pe branch ralph/echo-improve, nu pe master\n- Daca ralph.sh esueaza, marcheaza proiectul prin CLI wrapper:\n ```bash\n cd /home/moltbot/echo-core && source .venv/bin/activate && \\\n python3 -m src.approved_tasks_cli mark-failed --slug {name} --error \"MESAJ\"\n ```\n- Delay 5 secunde intre proiecte pentru a evita rate limiting\n", "allowed_tools": [ "Bash", "Read", diff --git a/dashboard/DESIGN.md b/dashboard/DESIGN.md new file mode 100644 index 0000000..088ea3a --- /dev/null +++ b/dashboard/DESIGN.md @@ -0,0 +1,317 @@ +# Echo Dashboard — Design System + +This document is the source of truth for visual decisions across the Echo +Dashboard (port 8088, served at `/echo/`). Tokens live in +`dashboard/static/tokens.css`. Page-level CSS is in `common.css` and per-page +` + + +
+ + +
+ + + + diff --git a/dashboard/ralph.html b/dashboard/ralph.html deleted file mode 100644 index e377467..0000000 --- a/dashboard/ralph.html +++ /dev/null @@ -1,743 +0,0 @@ - - - - - - - Echo · Ralph - - - - - - - - -
- - -
-
- -
Se încarcă proiectele Ralph...
-
-
-
- - - - - - - diff --git a/dashboard/static/fonts/inter-400.woff2 b/dashboard/static/fonts/inter-400.woff2 new file mode 100644 index 0000000..f15b025 Binary files /dev/null and b/dashboard/static/fonts/inter-400.woff2 differ diff --git a/dashboard/static/fonts/inter-500.woff2 b/dashboard/static/fonts/inter-500.woff2 new file mode 100644 index 0000000..54f0a59 Binary files /dev/null and b/dashboard/static/fonts/inter-500.woff2 differ diff --git a/dashboard/static/fonts/inter-600.woff2 b/dashboard/static/fonts/inter-600.woff2 new file mode 100644 index 0000000..d189794 Binary files /dev/null and b/dashboard/static/fonts/inter-600.woff2 differ diff --git a/dashboard/static/fonts/inter-700.woff2 b/dashboard/static/fonts/inter-700.woff2 new file mode 100644 index 0000000..a68fb10 Binary files /dev/null and b/dashboard/static/fonts/inter-700.woff2 differ diff --git a/dashboard/static/tokens.css b/dashboard/static/tokens.css new file mode 100644 index 0000000..15d7055 --- /dev/null +++ b/dashboard/static/tokens.css @@ -0,0 +1,159 @@ +/* + * Echo Dashboard — Design Tokens + * Single source of truth for all CSS variables, fonts, and shared + * mobile-modal behavior. Loaded via /echo/static/tokens.css on every + * dashboard page (in addition to common.css for now). + * + * Token coverage: + * - Colors (dark default + light theme override) + * - Status palette (running, blocked, failed, complete, idle, + * planning, pending, approved) + * - Typography (Inter sans + JetBrains Mono mono, size scale) + * - Spacing (8px grid) + * - Radius scale + * - Shadows / transitions + */ + +/* ========================================================== + @font-face — Inter (self-hosted, woff2 only) + ========================================================== */ +@font-face { + font-family: 'Inter'; + src: url('/echo/static/fonts/inter-400.woff2') format('woff2'); + font-weight: 400; + font-style: normal; + font-display: swap; +} + +@font-face { + font-family: 'Inter'; + src: url('/echo/static/fonts/inter-500.woff2') format('woff2'); + font-weight: 500; + font-style: normal; + font-display: swap; +} + +@font-face { + font-family: 'Inter'; + src: url('/echo/static/fonts/inter-600.woff2') format('woff2'); + font-weight: 600; + font-style: normal; + font-display: swap; +} + +@font-face { + font-family: 'Inter'; + src: url('/echo/static/fonts/inter-700.woff2') format('woff2'); + font-weight: 700; + font-style: normal; + font-display: swap; +} + +/* ========================================================== + Tokens — dark theme (default) + ========================================================== */ +:root { + /* Colors — dark surface */ + --bg-base: #13131a; + --bg-surface: rgba(255, 255, 255, 0.12); + --bg-surface-hover: rgba(255, 255, 255, 0.16); + --bg-surface-active: rgba(255, 255, 255, 0.20); + --bg-elevated: rgba(255, 255, 255, 0.14); + + --text-primary: #ffffff; + --text-secondary: #f5f5f5; + --text-muted: #e5e5e5; + + --accent: #3b82f6; + --accent-hover: #2563eb; + --accent-subtle: rgba(59, 130, 246, 0.2); + + --border: rgba(255, 255, 255, 0.3); + --border-focus: rgba(59, 130, 246, 0.7); + + --header-bg: rgba(19, 19, 26, 0.95); + + --success: #22c55e; + --warning: #eab308; + --error: #ef4444; + + /* Status palette — used by .status-pill[data-status] */ + --status-running: rgb(34, 197, 94); /* green — running-ralph / running-manual */ + --status-blocked: rgb(245, 158, 11); /* amber */ + --status-failed: rgb(239, 68, 68); /* red */ + --status-complete: rgb(156, 163, 175); /* slate (done = neutral) */ + --status-idle: var(--text-muted); + + /* Status palette — extended (workflow states) */ + --status-planning: rgb(167, 139, 250); /* violet — Echo is planning */ + --status-pending: rgb(96, 165, 250); /* sky — awaiting approval */ + --status-approved: rgb(234, 179, 8); /* gold — approved tonight */ + + /* Spacing — 8px grid */ + --space-1: 4px; + --space-2: 8px; + --space-3: 12px; + --space-4: 16px; + --space-5: 20px; + --space-6: 24px; + --space-8: 32px; + --space-10: 40px; + + /* Typography */ + --font-sans: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; + --font-mono: 'JetBrains Mono', 'Fira Code', ui-monospace, monospace; + + --text-xs: 0.75rem; + --text-sm: 0.875rem; + --text-base: 1rem; + --text-lg: 1.125rem; + --text-xl: 1.25rem; + + /* Radius */ + --radius-sm: 4px; + --radius-md: 8px; + --radius-lg: 12px; + --radius-full: 9999px; + + /* Shadows */ + --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.3); + --shadow-md: 0 4px 12px rgba(0, 0, 0, 0.4); + --shadow-lg: 0 8px 24px rgba(0, 0, 0, 0.5); + + /* Motion */ + --transition-fast: 0.15s ease; + --transition-base: 0.2s ease; +} + +/* ========================================================== + Light theme override + ========================================================== */ +[data-theme="light"] { + --bg-base: #f8f9fa; + --bg-surface: rgba(0, 0, 0, 0.04); + --bg-surface-hover: rgba(0, 0, 0, 0.08); + --bg-surface-active: rgba(0, 0, 0, 0.12); + --bg-elevated: rgba(0, 0, 0, 0.06); + + --text-primary: #1a1a1a; + --text-secondary: #444444; + --text-muted: #666666; + + --border: rgba(0, 0, 0, 0.12); + --border-focus: rgba(59, 130, 246, 0.5); + + --accent-subtle: rgba(59, 130, 246, 0.12); + + --header-bg: rgba(255, 255, 255, 0.95); +} + +/* ========================================================== + Mobile modal — shared across all pages with .modal-overlay + ========================================================== */ +@media (max-width: 640px) { + .modal-overlay { padding: 0; align-items: stretch; } + .modal { max-width: 100vw !important; max-height: 100vh !important; border-radius: 0; height: 100vh; } + .modal-header { position: sticky; top: 0; background: var(--bg-base); } + .modal-footer { position: sticky; bottom: 0; padding-bottom: max(var(--space-4), env(safe-area-inset-bottom)); } + .phase-stepper .phase-step:not(.active) span:not(.step-num) { display: none; } +} diff --git a/dashboard/workspace.html b/dashboard/workspace.html index bee2e26..0854eb6 100644 --- a/dashboard/workspace.html +++ b/dashboard/workspace.html @@ -5,271 +5,470 @@ Echo · Workspace + + + + @@ -425,571 +859,1405 @@
-
- -