Compare commits
7 Commits
1462f98ae9
...
176dc01aa6
| Author | SHA1 | Date | |
|---|---|---|---|
| 176dc01aa6 | |||
| 6d1d4bfeb5 | |||
| 77df09974c | |||
| 38259f3cfd | |||
| b08f039917 | |||
| fb7ca74ca1 | |||
| 8594f98bff |
@@ -3,8 +3,8 @@
|
||||
{
|
||||
"name": "romfast-website",
|
||||
"description": "analizeaza paginile din website si propune 1-3 pagini noi sau modificare de pagini cu ce ar face website-ul firmei mele Romfast (vinde ERP ROA) mai util, informational, educativ, cu scopul de a atrage lead-uri informate, calde",
|
||||
"status": "planning",
|
||||
"planning_session_id": "14d2d96d-d4eb-4472-9b07-4a869909c564",
|
||||
"status": "cancelled",
|
||||
"planning_session_id": null,
|
||||
"final_plan_path": null,
|
||||
"proposed_at": "2026-04-26T18:53:47.597827+00:00",
|
||||
"approved_at": null,
|
||||
@@ -14,8 +14,8 @@
|
||||
{
|
||||
"name": "space-booking",
|
||||
"description": "vreau sa pornesti aplicatia si sa testezi frontend in browser",
|
||||
"status": "planning",
|
||||
"planning_session_id": "d9c2f7ea-7e80-4cd3-b569-139b3fd01eb0",
|
||||
"status": "cancelled",
|
||||
"planning_session_id": null,
|
||||
"final_plan_path": null,
|
||||
"proposed_at": "2026-04-26T19:12:15.605405+00:00",
|
||||
"approved_at": null,
|
||||
@@ -25,7 +25,7 @@
|
||||
{
|
||||
"name": "roa2web-anaf-notificari",
|
||||
"description": "Integrare alerte ANAF Monitor direct \u00een roa2web: c\u00e2nd monitor_v2.py detecteaz\u0103 modific\u0103ri la D406/D394/D100/D390/E-Factura, trimite notificare automat\u0103 prin Telegram bot existent \u00een roa2web. UI simplu \u00een dashboard pentru vizualizare modific\u0103ri recente.",
|
||||
"status": "pending",
|
||||
"status": "cancelled",
|
||||
"proposed_at": "2026-04-27T21:01:29.004348",
|
||||
"approved_at": null,
|
||||
"started_at": null,
|
||||
@@ -34,7 +34,7 @@
|
||||
{
|
||||
"name": "roa2web-playwright-qa",
|
||||
"description": "QA automat pentru roa2web cu Playwright CLI + Claude Code: set de teste care verific\u0103 paginile principale (balan\u021b\u0103, facturi, trezorerie), detecteaz\u0103 regresii vizuale \u0219i func\u021bionale, raporteaz\u0103 \u00een dashboard. Rulare automat\u0103 la fiecare deploy.",
|
||||
"status": "pending",
|
||||
"status": "cancelled",
|
||||
"proposed_at": "2026-04-27T21:01:29.004348",
|
||||
"approved_at": null,
|
||||
"started_at": null,
|
||||
@@ -43,12 +43,13 @@
|
||||
{
|
||||
"name": "chatbot-maria-txt-converter",
|
||||
"description": "Script simplu care converte\u0219te fi\u0219iere TXT (scrise de angajatul nou) \u00een Markdown structurat pentru document store Flowise (chatbot Maria). Monitorizeaz\u0103 un folder, converte\u0219te automat \u0219i actualizeaz\u0103 document store.",
|
||||
"status": "pending",
|
||||
"status": "cancelled",
|
||||
"proposed_at": "2026-04-27T21:01:29.004348",
|
||||
"approved_at": null,
|
||||
"started_at": null,
|
||||
"pid": null
|
||||
}
|
||||
],
|
||||
"last_updated": "2026-04-28T06:47:51.312708+00:00"
|
||||
"last_updated": "2026-04-29T05:28:15.191588+00:00",
|
||||
"version": 7
|
||||
}
|
||||
@@ -37,9 +37,9 @@
|
||||
"report_on": "changes",
|
||||
"timeout": 120,
|
||||
"enabled": true,
|
||||
"last_run": "2026-04-28T10:00:00.001390+00:00",
|
||||
"last_run": "2026-04-29T16:00:00.002522+00:00",
|
||||
"last_status": "ok",
|
||||
"next_run": "2026-04-28T16:00:00+00:00"
|
||||
"next_run": "2026-04-30T10:00:00+00:00"
|
||||
},
|
||||
{
|
||||
"name": "security-audit-daily",
|
||||
@@ -53,9 +53,9 @@
|
||||
"report_on": "changes",
|
||||
"timeout": 180,
|
||||
"enabled": true,
|
||||
"last_run": "2026-04-28T03:00:00.002116+00:00",
|
||||
"last_run": "2026-04-29T03:00:00.002443+00:00",
|
||||
"last_status": "ok",
|
||||
"next_run": "2026-04-29T03:00:00+00:00"
|
||||
"next_run": "2026-04-30T03:00:00+00:00"
|
||||
},
|
||||
{
|
||||
"name": "kb-index-refresh",
|
||||
@@ -69,9 +69,9 @@
|
||||
"report_on": "never",
|
||||
"timeout": 120,
|
||||
"enabled": true,
|
||||
"last_run": "2026-04-28T03:30:00.001308+00:00",
|
||||
"last_run": "2026-04-29T03:30:00.003107+00:00",
|
||||
"last_status": "ok",
|
||||
"next_run": "2026-04-29T03:30:00+00:00"
|
||||
"next_run": "2026-04-30T03:30:00+00:00"
|
||||
},
|
||||
{
|
||||
"name": "archive-tasks-daily",
|
||||
@@ -85,9 +85,9 @@
|
||||
"report_on": "changes",
|
||||
"timeout": 60,
|
||||
"enabled": true,
|
||||
"last_run": "2026-04-28T03:00:00.001778+00:00",
|
||||
"last_run": "2026-04-29T03:00:00.002102+00:00",
|
||||
"last_status": "ok",
|
||||
"next_run": "2026-04-29T03:00:00+00:00"
|
||||
"next_run": "2026-04-30T03:00:00+00:00"
|
||||
},
|
||||
{
|
||||
"name": "backup-config",
|
||||
@@ -101,9 +101,9 @@
|
||||
"report_on": "never",
|
||||
"timeout": 120,
|
||||
"enabled": true,
|
||||
"last_run": "2026-04-28T02:00:00.002390+00:00",
|
||||
"last_run": "2026-04-29T02:00:00.001234+00:00",
|
||||
"last_status": "ok",
|
||||
"next_run": "2026-04-29T02:00:00+00:00"
|
||||
"next_run": "2026-04-30T02:00:00+00:00"
|
||||
},
|
||||
{
|
||||
"name": "insights-extract",
|
||||
@@ -185,9 +185,9 @@
|
||||
"enabled": true,
|
||||
"prompt": "RAPORT DIMINEAȚĂ - trimite pe EMAIL (Gmail: mmarius28@gmail.com)\n\n## CALENDAR\nVerifică calendarul:\n```bash\ncd ~/echo-core && source venv/bin/activate && python3 tools/calendar_check.py today\npython3 tools/calendar_check.py travel\npython3 tools/calendar_check.py week\n```\n\n## CITEȘTE CONTEXT\n- USER.md pentru programul lui Marius (luni-joi 15-16 liber)\n- memory/kb/insights/ pentru propuneri (ultimele 3 zile)\n- /home/moltbot/echo-core/approved-tasks.json pentru status proiecte/features (câmpurile: name, status, started_at, pid)\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. CALENDAR\n- 📅 **AZI:** [evenimente]\n- 📅 **MÂINE:** [evenimente]\n- 📅 **PESTE 2 ZILE:** [dacă e GRUP, NLP, meeting mare]\n- 🚂 **TRAVEL:** Reminders bilete+cazare\n\n### 2. PROIECTE/FEATURES NOAPTEA 💻\n\nCitesc /home/moltbot/echo-core/approved-tasks.json și raportez ce s-a realizat:\n(statusuri: pending, approved, running, complete, failed, stopped)\nPentru stories done/total: citesc /home/moltbot/workspace/{name}/scripts/ralph/prd.json\n\n**Format pentru fiecare proiect/feature [x]:**\n\n```html\n<div style=\"background: #d1fae5; padding: 15px; margin: 10px 0; border-radius: 8px;\">\n <h3>✅ P1 - Nume Proiect</h3>\n \n <p><strong>Status:</strong> X/Y stories complete</p>\n \n <p><strong>Stories realizate:</strong></p>\n <ul>\n <li>✅ US-001: Titlu story - implementat cu succes</li>\n <li>✅ US-002: Titlu story - quality checks pass</li>\n <li>🔄 US-003: Titlu story - în progres (blocat pe dependency)</li>\n </ul>\n \n <p><strong>Link:</strong> <a href=\"https://gitea.romfast.ro/romfast/PROJECT-NAME\">gitea.romfast.ro/romfast/PROJECT-NAME</a></p>\n \n <p><strong>Learnings:</strong> [din progress.txt - ce patterns am descoperit]</p>\n \n <p><strong>Next steps:</strong> [ce rămâne de făcut]</p>\n</div>\n```\n\n**Dacă NU s-au executat proiecte/features:**\n- Sari peste această secțiune\n\n### 3. STATUS GENERAL\n- Ce s-a făcut ieri (joburi, taskuri)\n- Git status ~/clawd\n- Joburi executate (YouTube, insights, etc.)\n\n### 4. PROPUNERI CU ZI ȘI ORĂ!\n\n**OBLIGATORIU:** Fiecare propunere TU+EU sau FAC TU trebuie să aibă ZI și ORĂ concrete!\n\nCategorii:\n- 🤖 **FAC EU** (0 efort) - execut singur\n- 🤝 **TU+EU** (eu pregătesc) - cu zi/oră!\n- 👤 **FAC TU** (template gata) - cu zi/oră!\n\nExemplu:\n- **A1 - Sesiune Dizolvare Vină** 🤝 TU+EU\n 📅 **Marți 3 feb, 15:00-15:30**\n Context + link sursă\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\n### 5. INSIGHTS DISPONIBILE\n\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- Alt orar = \"A1 miercuri nu marți\"\n\n## TRIMITERE\npython3 /home/moltbot/echo-core/tools/email_send.py \"mmarius28@gmail.com\" \"Raport Dimineata DATA\" \"HTML_CONTENT\"\n\nNU trimite pe Discord - doar email.",
|
||||
"allowed_tools": [],
|
||||
"last_run": "2026-04-28T08:30:00.001148+00:00",
|
||||
"last_status": "error",
|
||||
"next_run": "2026-04-29T08:30:00+00:00"
|
||||
"last_run": "2026-04-29T08:30:00.002215+00:00",
|
||||
"last_status": "ok",
|
||||
"next_run": "2026-04-30T08:30:00+00:00"
|
||||
},
|
||||
{
|
||||
"name": "evening-report",
|
||||
@@ -197,9 +197,9 @@
|
||||
"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.",
|
||||
"allowed_tools": [],
|
||||
"last_run": "2026-04-27T21:00:00.003134+00:00",
|
||||
"last_run": "2026-04-28T21:00:00.001282+00:00",
|
||||
"last_status": "ok",
|
||||
"next_run": "2026-04-28T21:00:00+00:00"
|
||||
"next_run": "2026-04-29T21:00:00+00:00"
|
||||
},
|
||||
{
|
||||
"name": "morning-coaching",
|
||||
@@ -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-28T10:00:00.001811+00:00",
|
||||
"last_run": "2026-04-29T16:00:00.003223+00:00",
|
||||
"last_status": "ok",
|
||||
"next_run": "2026-04-28T12:00:00+00:00"
|
||||
"next_run": "2026-04-29T18:00:00+00:00"
|
||||
},
|
||||
{
|
||||
"name": "night-execute",
|
||||
@@ -285,8 +285,8 @@
|
||||
"Read",
|
||||
"Write"
|
||||
],
|
||||
"last_run": "2026-04-27T23:00:00.001665+00:00",
|
||||
"last_run": "2026-04-28T23:00:00.002213+00:00",
|
||||
"last_status": "ok",
|
||||
"next_run": "2026-04-28T23:00:00+00:00"
|
||||
"next_run": "2026-04-29T23:00:00+00:00"
|
||||
}
|
||||
]
|
||||
|
||||
@@ -10,6 +10,7 @@ import os
|
||||
import sys
|
||||
from http.server import SimpleHTTPRequestHandler, ThreadingHTTPServer
|
||||
from pathlib import Path
|
||||
from urllib.parse import quote as _urlquote, parse_qs, urlparse
|
||||
|
||||
# Make dashboard/ importable for the handler submodules (constants,
|
||||
# habits_helpers, handlers.*). Tests rely on this as well.
|
||||
@@ -242,11 +243,19 @@ class TaskBoardHandler(
|
||||
return
|
||||
elif self.path in ('/echo/login', '/login') or \
|
||||
self.path.startswith(('/echo/login?', '/login?')):
|
||||
# If already logged in, redirect to workspace; otherwise serve
|
||||
# login.html (created in Lane B2).
|
||||
# If already logged in, redirect to next (or workspace); otherwise serve login.html.
|
||||
if self._check_dashboard_cookie():
|
||||
qs = parse_qs(urlparse(self.path).query)
|
||||
next_vals = qs.get('next', [])
|
||||
nxt = next_vals[0] if next_vals else ''
|
||||
# Proxy strips /echo/ before Python, so nxt is e.g. /workspace.html.
|
||||
# Re-add the prefix so the browser lands on the right public URL.
|
||||
if nxt and nxt.startswith('/') and '://' not in nxt:
|
||||
dest = '/echo' + nxt
|
||||
else:
|
||||
dest = '/echo/workspace.html'
|
||||
self.send_response(302)
|
||||
self.send_header('Location', '/echo/workspace.html')
|
||||
self.send_header('Location', dest)
|
||||
self.send_header('Content-Length', '0')
|
||||
self.end_headers()
|
||||
return
|
||||
@@ -284,7 +293,8 @@ class TaskBoardHandler(
|
||||
if fpath.is_file():
|
||||
if fpath.name != 'login.html' and not self._check_dashboard_cookie():
|
||||
self.send_response(302)
|
||||
self.send_header('Location', '/echo/login')
|
||||
next_param = _urlquote(self.path, safe='/?=&#')
|
||||
self.send_header('Location', f'/echo/login?next={next_param}')
|
||||
self.send_header('Content-Length', '0')
|
||||
self.end_headers()
|
||||
return
|
||||
|
||||
@@ -9,6 +9,7 @@ ExecStart=/home/moltbot/echo-core/.venv/bin/python3 /home/moltbot/echo-core/dash
|
||||
Restart=on-failure
|
||||
RestartSec=5
|
||||
Environment=PYTHONUNBUFFERED=1
|
||||
Environment=PATH=/home/moltbot/.local/bin:/usr/local/bin:/usr/bin:/bin
|
||||
StandardOutput=append:/home/moltbot/echo-core/logs/echo-taskboard.log
|
||||
StandardError=append:/home/moltbot/echo-core/logs/echo-taskboard.log
|
||||
|
||||
|
||||
@@ -1807,10 +1807,13 @@
|
||||
});
|
||||
|
||||
function getPathFromURL() {
|
||||
// ?file= survives login redirects; #hash works when already logged in.
|
||||
const qp = new URLSearchParams(window.location.search).get('file');
|
||||
if (qp) return decodeURIComponent(qp);
|
||||
const hash = window.location.hash;
|
||||
return hash ? decodeURIComponent(hash.slice(1)) : '';
|
||||
}
|
||||
|
||||
|
||||
window.addEventListener('hashchange', () => loadPath(getPathFromURL()));
|
||||
|
||||
document.getElementById('codeEditor').addEventListener('input', function() {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"lastUpdated": "2026-04-21T13:40:29.984484",
|
||||
"lastUpdated": "2026-04-29T05:30:59.129949",
|
||||
"habits": [
|
||||
{
|
||||
"id": "95c15eef-3a14-4985-a61e-0b64b72851b0",
|
||||
@@ -78,7 +78,7 @@
|
||||
"streak": {
|
||||
"current": 1,
|
||||
"best": 6,
|
||||
"lastCheckIn": "2026-02-23"
|
||||
"lastCheckIn": "2026-04-29"
|
||||
},
|
||||
"lives": 4,
|
||||
"completions": [
|
||||
@@ -113,893 +113,15 @@
|
||||
{
|
||||
"date": "2026-02-23",
|
||||
"type": "check"
|
||||
},
|
||||
{
|
||||
"date": "2026-04-29",
|
||||
"type": "check"
|
||||
}
|
||||
],
|
||||
"createdAt": "2026-02-11T01:58:44.779904",
|
||||
"updatedAt": "2026-02-23T13:08:19.884995",
|
||||
"updatedAt": "2026-04-29T05:30:59.129949",
|
||||
"lastLivesAward": "2026-02-23"
|
||||
},
|
||||
{
|
||||
"id": "a34a1d67-64f4-4330-bae1-ecc3abda02fb",
|
||||
"name": "Morning Exercise",
|
||||
"category": "health",
|
||||
"color": "#10b981",
|
||||
"icon": "dumbbell",
|
||||
"priority": 1,
|
||||
"notes": "Start with 10 push-ups",
|
||||
"reminderTime": "07:00",
|
||||
"frequency": {
|
||||
"type": "daily"
|
||||
},
|
||||
"streak": {
|
||||
"current": 0,
|
||||
"best": 0,
|
||||
"lastCheckIn": null
|
||||
},
|
||||
"lives": 3,
|
||||
"completions": [],
|
||||
"createdAt": "2026-04-21T13:39:56.225487",
|
||||
"updatedAt": "2026-04-21T13:39:56.225487"
|
||||
},
|
||||
{
|
||||
"id": "c38aa0d6-1baf-43a7-8020-aaed45eec38b",
|
||||
"name": "Daily Reading",
|
||||
"category": "other",
|
||||
"color": "#3b82f6",
|
||||
"icon": "check-circle",
|
||||
"priority": 5,
|
||||
"notes": "",
|
||||
"reminderTime": "",
|
||||
"frequency": {
|
||||
"type": "daily"
|
||||
},
|
||||
"streak": {
|
||||
"current": 0,
|
||||
"best": 0,
|
||||
"lastCheckIn": null
|
||||
},
|
||||
"lives": 3,
|
||||
"completions": [],
|
||||
"createdAt": "2026-04-21T13:40:00.242264",
|
||||
"updatedAt": "2026-04-21T13:40:00.242264"
|
||||
},
|
||||
{
|
||||
"id": "21dc9ac0-ad31-4bd3-bdd0-eee3a05e9996",
|
||||
"name": "Low Priority",
|
||||
"category": "other",
|
||||
"color": "#3b82f6",
|
||||
"icon": "check-circle",
|
||||
"priority": 10,
|
||||
"notes": "",
|
||||
"reminderTime": "",
|
||||
"frequency": {
|
||||
"type": "daily"
|
||||
},
|
||||
"streak": {
|
||||
"current": 0,
|
||||
"best": 0,
|
||||
"lastCheckIn": null
|
||||
},
|
||||
"lives": 3,
|
||||
"completions": [],
|
||||
"createdAt": "2026-04-21T13:40:01.101343",
|
||||
"updatedAt": "2026-04-21T13:40:01.101343"
|
||||
},
|
||||
{
|
||||
"id": "b9c48ef6-88ff-430c-95dc-b26eb41f15a9",
|
||||
"name": "High Priority",
|
||||
"category": "other",
|
||||
"color": "#3b82f6",
|
||||
"icon": "check-circle",
|
||||
"priority": 1,
|
||||
"notes": "",
|
||||
"reminderTime": "",
|
||||
"frequency": {
|
||||
"type": "daily"
|
||||
},
|
||||
"streak": {
|
||||
"current": 0,
|
||||
"best": 0,
|
||||
"lastCheckIn": null
|
||||
},
|
||||
"lives": 3,
|
||||
"completions": [],
|
||||
"createdAt": "2026-04-21T13:40:01.102455",
|
||||
"updatedAt": "2026-04-21T13:40:01.102455"
|
||||
},
|
||||
{
|
||||
"id": "a5410380-d3fa-452c-b0c8-c2aeb3314b7a",
|
||||
"name": "Medium Priority",
|
||||
"category": "other",
|
||||
"color": "#3b82f6",
|
||||
"icon": "check-circle",
|
||||
"priority": 5,
|
||||
"notes": "",
|
||||
"reminderTime": "",
|
||||
"frequency": {
|
||||
"type": "daily"
|
||||
},
|
||||
"streak": {
|
||||
"current": 0,
|
||||
"best": 0,
|
||||
"lastCheckIn": null
|
||||
},
|
||||
"lives": 3,
|
||||
"completions": [],
|
||||
"createdAt": "2026-04-21T13:40:01.103459",
|
||||
"updatedAt": "2026-04-21T13:40:01.103459"
|
||||
},
|
||||
{
|
||||
"id": "302ece43-2972-4541-b8d0-6451dce474bf",
|
||||
"name": "Test Habit",
|
||||
"category": "other",
|
||||
"color": "#3b82f6",
|
||||
"icon": "check-circle",
|
||||
"priority": 5,
|
||||
"notes": "",
|
||||
"reminderTime": "",
|
||||
"frequency": {
|
||||
"type": "daily"
|
||||
},
|
||||
"streak": {
|
||||
"current": 0,
|
||||
"best": 0,
|
||||
"lastCheckIn": null
|
||||
},
|
||||
"lives": 3,
|
||||
"completions": [],
|
||||
"createdAt": "2026-04-21T13:40:02.723973",
|
||||
"updatedAt": "2026-04-21T13:40:02.723973"
|
||||
},
|
||||
{
|
||||
"id": "9ffe612d-2f84-4b75-b589-04457b93109b",
|
||||
"name": "Updated Name",
|
||||
"category": "productivity",
|
||||
"color": "#ef4444",
|
||||
"icon": "check-circle",
|
||||
"priority": 1,
|
||||
"notes": "New notes",
|
||||
"reminderTime": "",
|
||||
"frequency": {
|
||||
"type": "daily"
|
||||
},
|
||||
"streak": {
|
||||
"current": 0,
|
||||
"best": 0,
|
||||
"lastCheckIn": null
|
||||
},
|
||||
"lives": 3,
|
||||
"completions": [],
|
||||
"createdAt": "2026-04-21T13:40:03.528071",
|
||||
"updatedAt": "2026-04-21T13:40:03.529399"
|
||||
},
|
||||
{
|
||||
"id": "c61e531c-26e0-4223-be38-e3d77e3202d1",
|
||||
"name": "Updated Name",
|
||||
"category": "other",
|
||||
"color": "#3b82f6",
|
||||
"icon": "check-circle",
|
||||
"priority": 5,
|
||||
"notes": "",
|
||||
"reminderTime": "",
|
||||
"frequency": {
|
||||
"type": "daily"
|
||||
},
|
||||
"streak": {
|
||||
"current": 0,
|
||||
"best": 0,
|
||||
"lastCheckIn": null
|
||||
},
|
||||
"lives": 3,
|
||||
"completions": [],
|
||||
"createdAt": "2026-04-21T13:40:04.332914",
|
||||
"updatedAt": "2026-04-21T13:40:04.334508"
|
||||
},
|
||||
{
|
||||
"id": "71388af9-fcab-4910-a5d6-74a27cc4676d",
|
||||
"name": "Test Habit",
|
||||
"category": "other",
|
||||
"color": "#3b82f6",
|
||||
"icon": "check-circle",
|
||||
"priority": 5,
|
||||
"notes": "",
|
||||
"reminderTime": "",
|
||||
"frequency": {
|
||||
"type": "daily"
|
||||
},
|
||||
"streak": {
|
||||
"current": 0,
|
||||
"best": 0,
|
||||
"lastCheckIn": null
|
||||
},
|
||||
"lives": 3,
|
||||
"completions": [],
|
||||
"createdAt": "2026-04-21T13:40:05.941683",
|
||||
"updatedAt": "2026-04-21T13:40:05.941683"
|
||||
},
|
||||
{
|
||||
"id": "edb52e78-e6e0-4a03-973f-0839690bb8ae",
|
||||
"name": "Habit to Delete",
|
||||
"category": "other",
|
||||
"color": "#3b82f6",
|
||||
"icon": "check-circle",
|
||||
"priority": 5,
|
||||
"notes": "",
|
||||
"reminderTime": "",
|
||||
"frequency": {
|
||||
"type": "daily"
|
||||
},
|
||||
"streak": {
|
||||
"current": 0,
|
||||
"best": 0,
|
||||
"lastCheckIn": null
|
||||
},
|
||||
"lives": 3,
|
||||
"completions": [],
|
||||
"createdAt": "2026-04-21T13:40:06.749371",
|
||||
"updatedAt": "2026-04-21T13:40:06.749371"
|
||||
},
|
||||
{
|
||||
"id": "595ce224-d2b9-4ce5-b334-2fec32d388ad",
|
||||
"name": "Morning Exercise",
|
||||
"category": "other",
|
||||
"color": "#3b82f6",
|
||||
"icon": "check-circle",
|
||||
"priority": 5,
|
||||
"notes": "",
|
||||
"reminderTime": "",
|
||||
"frequency": {
|
||||
"type": "daily"
|
||||
},
|
||||
"streak": {
|
||||
"current": 1,
|
||||
"best": 1,
|
||||
"lastCheckIn": "2026-04-21"
|
||||
},
|
||||
"lives": 3,
|
||||
"completions": [
|
||||
{
|
||||
"date": "2026-04-21",
|
||||
"type": "check"
|
||||
}
|
||||
],
|
||||
"createdAt": "2026-04-21T13:40:09.177939",
|
||||
"updatedAt": "2026-04-21T13:40:09.180079"
|
||||
},
|
||||
{
|
||||
"id": "62c9952e-6f6b-47ac-91e3-22cf277767fe",
|
||||
"name": "Meditation",
|
||||
"category": "other",
|
||||
"color": "#3b82f6",
|
||||
"icon": "check-circle",
|
||||
"priority": 5,
|
||||
"notes": "",
|
||||
"reminderTime": "",
|
||||
"frequency": {
|
||||
"type": "daily"
|
||||
},
|
||||
"streak": {
|
||||
"current": 1,
|
||||
"best": 1,
|
||||
"lastCheckIn": "2026-04-21"
|
||||
},
|
||||
"lives": 3,
|
||||
"completions": [
|
||||
{
|
||||
"date": "2026-04-21",
|
||||
"type": "check",
|
||||
"note": "Felt very relaxed today",
|
||||
"rating": 5,
|
||||
"mood": "happy"
|
||||
}
|
||||
],
|
||||
"createdAt": "2026-04-21T13:40:09.983840",
|
||||
"updatedAt": "2026-04-21T13:40:09.985357"
|
||||
},
|
||||
{
|
||||
"id": "f3065043-265b-404f-916e-f662f3d17c66",
|
||||
"name": "Monday Only Habit",
|
||||
"category": "other",
|
||||
"color": "#3b82f6",
|
||||
"icon": "check-circle",
|
||||
"priority": 5,
|
||||
"notes": "",
|
||||
"reminderTime": "",
|
||||
"frequency": {
|
||||
"type": "specific_days",
|
||||
"days": [
|
||||
2
|
||||
]
|
||||
},
|
||||
"streak": {
|
||||
"current": 0,
|
||||
"best": 0,
|
||||
"lastCheckIn": null
|
||||
},
|
||||
"lives": 3,
|
||||
"completions": [],
|
||||
"createdAt": "2026-04-21T13:40:11.592610",
|
||||
"updatedAt": "2026-04-21T13:40:11.592610"
|
||||
},
|
||||
{
|
||||
"id": "b97c524e-c243-48da-9d47-4646206806d1",
|
||||
"name": "Water Plants",
|
||||
"category": "other",
|
||||
"color": "#3b82f6",
|
||||
"icon": "check-circle",
|
||||
"priority": 5,
|
||||
"notes": "",
|
||||
"reminderTime": "",
|
||||
"frequency": {
|
||||
"type": "daily"
|
||||
},
|
||||
"streak": {
|
||||
"current": 1,
|
||||
"best": 1,
|
||||
"lastCheckIn": "2026-04-21"
|
||||
},
|
||||
"lives": 3,
|
||||
"completions": [
|
||||
{
|
||||
"date": "2026-04-21",
|
||||
"type": "check"
|
||||
}
|
||||
],
|
||||
"createdAt": "2026-04-21T13:40:12.398205",
|
||||
"updatedAt": "2026-04-21T13:40:12.399838"
|
||||
},
|
||||
{
|
||||
"id": "21e3c623-3370-4ccc-84a8-e468277ed93a",
|
||||
"name": "Read",
|
||||
"category": "other",
|
||||
"color": "#3b82f6",
|
||||
"icon": "check-circle",
|
||||
"priority": 5,
|
||||
"notes": "",
|
||||
"reminderTime": "",
|
||||
"frequency": {
|
||||
"type": "daily"
|
||||
},
|
||||
"streak": {
|
||||
"current": 1,
|
||||
"best": 1,
|
||||
"lastCheckIn": "2026-04-21"
|
||||
},
|
||||
"lives": 3,
|
||||
"completions": [
|
||||
{
|
||||
"date": "2026-04-21",
|
||||
"type": "check"
|
||||
}
|
||||
],
|
||||
"createdAt": "2026-04-21T13:40:13.204268",
|
||||
"updatedAt": "2026-04-21T13:40:13.205755"
|
||||
},
|
||||
{
|
||||
"id": "c71332bd-c0f2-4e79-bb29-97bb513cc5f1",
|
||||
"name": "Floss",
|
||||
"category": "other",
|
||||
"color": "#3b82f6",
|
||||
"icon": "check-circle",
|
||||
"priority": 5,
|
||||
"notes": "",
|
||||
"reminderTime": "",
|
||||
"frequency": {
|
||||
"type": "daily"
|
||||
},
|
||||
"streak": {
|
||||
"current": 1,
|
||||
"best": 1,
|
||||
"lastCheckIn": "2026-04-21"
|
||||
},
|
||||
"lives": 3,
|
||||
"completions": [
|
||||
{
|
||||
"date": "2026-04-21",
|
||||
"type": "check"
|
||||
}
|
||||
],
|
||||
"createdAt": "2026-04-21T13:40:14.009917",
|
||||
"updatedAt": "2026-04-21T13:40:14.011571"
|
||||
},
|
||||
{
|
||||
"id": "4057bfad-6754-493b-be59-8e6d00a9426b",
|
||||
"name": "Yoga",
|
||||
"category": "other",
|
||||
"color": "#3b82f6",
|
||||
"icon": "check-circle",
|
||||
"priority": 5,
|
||||
"notes": "",
|
||||
"reminderTime": "",
|
||||
"frequency": {
|
||||
"type": "daily"
|
||||
},
|
||||
"streak": {
|
||||
"current": 1,
|
||||
"best": 1,
|
||||
"lastCheckIn": "2026-04-21"
|
||||
},
|
||||
"lives": 3,
|
||||
"completions": [
|
||||
{
|
||||
"date": "2026-04-21",
|
||||
"type": "check"
|
||||
}
|
||||
],
|
||||
"createdAt": "2026-04-21T13:40:14.814725",
|
||||
"updatedAt": "2026-04-21T13:40:14.816582"
|
||||
},
|
||||
{
|
||||
"id": "135607ac-44c9-4dc5-b8b6-dcb958680e3a",
|
||||
"name": "Journal",
|
||||
"category": "other",
|
||||
"color": "#3b82f6",
|
||||
"icon": "check-circle",
|
||||
"priority": 5,
|
||||
"notes": "",
|
||||
"reminderTime": "",
|
||||
"frequency": {
|
||||
"type": "daily"
|
||||
},
|
||||
"streak": {
|
||||
"current": 0,
|
||||
"best": 0,
|
||||
"lastCheckIn": null
|
||||
},
|
||||
"lives": 3,
|
||||
"completions": [],
|
||||
"createdAt": "2026-04-21T13:40:15.620420",
|
||||
"updatedAt": "2026-04-21T13:40:15.620420"
|
||||
},
|
||||
{
|
||||
"id": "6166cffa-0bf6-4088-a552-ce8961a6f3d3",
|
||||
"name": "Gratitude",
|
||||
"category": "other",
|
||||
"color": "#3b82f6",
|
||||
"icon": "check-circle",
|
||||
"priority": 5,
|
||||
"notes": "",
|
||||
"reminderTime": "",
|
||||
"frequency": {
|
||||
"type": "daily"
|
||||
},
|
||||
"streak": {
|
||||
"current": 0,
|
||||
"best": 0,
|
||||
"lastCheckIn": null
|
||||
},
|
||||
"lives": 3,
|
||||
"completions": [],
|
||||
"createdAt": "2026-04-21T13:40:16.425718",
|
||||
"updatedAt": "2026-04-21T13:40:16.425718"
|
||||
},
|
||||
{
|
||||
"id": "f865fb79-e1a9-4eb4-a36d-f1b048db5095",
|
||||
"name": "Daily Exercise",
|
||||
"category": "other",
|
||||
"color": "#3b82f6",
|
||||
"icon": "check-circle",
|
||||
"priority": 5,
|
||||
"notes": "",
|
||||
"reminderTime": "",
|
||||
"frequency": {
|
||||
"type": "daily"
|
||||
},
|
||||
"streak": {
|
||||
"current": 0,
|
||||
"best": 0,
|
||||
"lastCheckIn": null
|
||||
},
|
||||
"lives": 2,
|
||||
"completions": [
|
||||
{
|
||||
"date": "2026-04-21",
|
||||
"type": "skip"
|
||||
}
|
||||
],
|
||||
"createdAt": "2026-04-21T13:40:17.230280",
|
||||
"updatedAt": "2026-04-21T13:40:17.231880"
|
||||
},
|
||||
{
|
||||
"id": "6926b37a-4b2a-4334-b382-bbacd2f3fa38",
|
||||
"name": "Daily Exercise",
|
||||
"category": "other",
|
||||
"color": "#3b82f6",
|
||||
"icon": "check-circle",
|
||||
"priority": 5,
|
||||
"notes": "",
|
||||
"reminderTime": "",
|
||||
"frequency": {
|
||||
"type": "daily"
|
||||
},
|
||||
"streak": {
|
||||
"current": 1,
|
||||
"best": 1,
|
||||
"lastCheckIn": "2026-04-21"
|
||||
},
|
||||
"lives": 3,
|
||||
"completions": [
|
||||
{
|
||||
"date": "2026-04-21",
|
||||
"type": "check"
|
||||
}
|
||||
],
|
||||
"createdAt": "2026-04-21T13:40:18.035252",
|
||||
"updatedAt": "2026-04-21T13:40:18.036876"
|
||||
},
|
||||
{
|
||||
"id": "13ca7da8-f9f9-4d04-abe1-72d9e018f729",
|
||||
"name": "Daily Exercise",
|
||||
"category": "other",
|
||||
"color": "#3b82f6",
|
||||
"icon": "check-circle",
|
||||
"priority": 5,
|
||||
"notes": "",
|
||||
"reminderTime": "",
|
||||
"frequency": {
|
||||
"type": "daily"
|
||||
},
|
||||
"streak": {
|
||||
"current": 0,
|
||||
"best": 0,
|
||||
"lastCheckIn": null
|
||||
},
|
||||
"lives": 0,
|
||||
"completions": [
|
||||
{
|
||||
"date": "2026-04-21",
|
||||
"type": "skip"
|
||||
},
|
||||
{
|
||||
"date": "2026-04-21",
|
||||
"type": "skip"
|
||||
},
|
||||
{
|
||||
"date": "2026-04-21",
|
||||
"type": "skip"
|
||||
}
|
||||
],
|
||||
"createdAt": "2026-04-21T13:40:19.658427",
|
||||
"updatedAt": "2026-04-21T13:40:19.663718"
|
||||
},
|
||||
{
|
||||
"id": "100b4b01-10ab-435a-a269-4413fb86e7c8",
|
||||
"name": "Daily Exercise",
|
||||
"category": "other",
|
||||
"color": "#3b82f6",
|
||||
"icon": "check-circle",
|
||||
"priority": 5,
|
||||
"notes": "",
|
||||
"reminderTime": "",
|
||||
"frequency": {
|
||||
"type": "daily"
|
||||
},
|
||||
"streak": {
|
||||
"current": 0,
|
||||
"best": 0,
|
||||
"lastCheckIn": null
|
||||
},
|
||||
"lives": 2,
|
||||
"completions": [
|
||||
{
|
||||
"date": "2026-04-21",
|
||||
"type": "skip"
|
||||
}
|
||||
],
|
||||
"createdAt": "2026-04-21T13:40:20.469061",
|
||||
"updatedAt": "2026-04-21T13:40:20.470855"
|
||||
},
|
||||
{
|
||||
"id": "cf0cb657-f384-4a0d-a3a5-83bff1a1acaa",
|
||||
"name": "Daily Exercise",
|
||||
"category": "other",
|
||||
"color": "#3b82f6",
|
||||
"icon": "check-circle",
|
||||
"priority": 5,
|
||||
"notes": "",
|
||||
"reminderTime": "",
|
||||
"frequency": {
|
||||
"type": "daily"
|
||||
},
|
||||
"streak": {
|
||||
"current": 0,
|
||||
"best": 1,
|
||||
"lastCheckIn": "2026-04-21"
|
||||
},
|
||||
"lives": 3,
|
||||
"completions": [],
|
||||
"createdAt": "2026-04-21T13:40:21.274674",
|
||||
"updatedAt": "2026-04-21T13:40:21.278631"
|
||||
},
|
||||
{
|
||||
"id": "1e5ac598-0984-4d5e-b5ff-59d29e95ce7b",
|
||||
"name": "Daily Exercise",
|
||||
"category": "other",
|
||||
"color": "#3b82f6",
|
||||
"icon": "check-circle",
|
||||
"priority": 5,
|
||||
"notes": "",
|
||||
"reminderTime": "",
|
||||
"frequency": {
|
||||
"type": "daily"
|
||||
},
|
||||
"streak": {
|
||||
"current": 0,
|
||||
"best": 0,
|
||||
"lastCheckIn": null
|
||||
},
|
||||
"lives": 3,
|
||||
"completions": [],
|
||||
"createdAt": "2026-04-21T13:40:22.082884",
|
||||
"updatedAt": "2026-04-21T13:40:22.082884"
|
||||
},
|
||||
{
|
||||
"id": "4ca5ce94-52d8-44ab-9a52-07c4ba736d00",
|
||||
"name": "Daily Exercise",
|
||||
"category": "other",
|
||||
"color": "#3b82f6",
|
||||
"icon": "check-circle",
|
||||
"priority": 5,
|
||||
"notes": "",
|
||||
"reminderTime": "",
|
||||
"frequency": {
|
||||
"type": "daily"
|
||||
},
|
||||
"streak": {
|
||||
"current": 0,
|
||||
"best": 0,
|
||||
"lastCheckIn": null
|
||||
},
|
||||
"lives": 3,
|
||||
"completions": [],
|
||||
"createdAt": "2026-04-21T13:40:23.691843",
|
||||
"updatedAt": "2026-04-21T13:40:23.691843"
|
||||
},
|
||||
{
|
||||
"id": "de01102c-e58a-4215-aee3-73211cbca676",
|
||||
"name": "Daily Exercise",
|
||||
"category": "other",
|
||||
"color": "#3b82f6",
|
||||
"icon": "check-circle",
|
||||
"priority": 5,
|
||||
"notes": "",
|
||||
"reminderTime": "",
|
||||
"frequency": {
|
||||
"type": "daily"
|
||||
},
|
||||
"streak": {
|
||||
"current": 0,
|
||||
"best": 1,
|
||||
"lastCheckIn": "2026-04-21"
|
||||
},
|
||||
"lives": 3,
|
||||
"completions": [],
|
||||
"createdAt": "2026-04-21T13:40:24.514309",
|
||||
"updatedAt": "2026-04-21T13:40:24.518328"
|
||||
},
|
||||
{
|
||||
"id": "6dc26d9f-9631-447e-8669-a36a7b41656a",
|
||||
"name": "Daily Exercise",
|
||||
"category": "other",
|
||||
"color": "#3b82f6",
|
||||
"icon": "check-circle",
|
||||
"priority": 5,
|
||||
"notes": "",
|
||||
"reminderTime": "",
|
||||
"frequency": {
|
||||
"type": "daily"
|
||||
},
|
||||
"streak": {
|
||||
"current": 0,
|
||||
"best": 0,
|
||||
"lastCheckIn": null
|
||||
},
|
||||
"lives": 3,
|
||||
"completions": [],
|
||||
"createdAt": "2026-04-21T13:40:25.322498",
|
||||
"updatedAt": "2026-04-21T13:40:25.322498"
|
||||
},
|
||||
{
|
||||
"id": "58b22147-ea36-4219-ac8a-488df8d7dc0a",
|
||||
"name": "Morning meditation",
|
||||
"category": "health",
|
||||
"color": "#10B981",
|
||||
"icon": "brain",
|
||||
"priority": 50,
|
||||
"notes": "",
|
||||
"reminderTime": "",
|
||||
"frequency": {
|
||||
"type": "daily"
|
||||
},
|
||||
"streak": {
|
||||
"current": 1,
|
||||
"best": 1,
|
||||
"lastCheckIn": "2026-04-21"
|
||||
},
|
||||
"lives": 3,
|
||||
"completions": [
|
||||
{
|
||||
"date": "2026-04-21",
|
||||
"type": "check"
|
||||
}
|
||||
],
|
||||
"createdAt": "2026-04-21T13:40:26.420091",
|
||||
"updatedAt": "2026-04-21T13:40:26.421942"
|
||||
},
|
||||
{
|
||||
"id": "00b8e0d2-f146-4446-89c1-42b5efe9b2c6",
|
||||
"name": "Daily exercise",
|
||||
"category": "health",
|
||||
"color": "#EF4444",
|
||||
"icon": "dumbbell",
|
||||
"priority": 50,
|
||||
"notes": "",
|
||||
"reminderTime": "",
|
||||
"frequency": {
|
||||
"type": "daily"
|
||||
},
|
||||
"streak": {
|
||||
"current": 0,
|
||||
"best": 0,
|
||||
"lastCheckIn": null
|
||||
},
|
||||
"lives": 3,
|
||||
"completions": [],
|
||||
"createdAt": "2026-04-21T13:40:26.925543",
|
||||
"updatedAt": "2026-04-21T13:40:26.925543"
|
||||
},
|
||||
{
|
||||
"id": "3f97d521-c2eb-4d7d-a5b9-97b99e21fb5a",
|
||||
"name": "Read book",
|
||||
"category": "growth",
|
||||
"color": "#3B82F6",
|
||||
"icon": "book",
|
||||
"priority": 50,
|
||||
"notes": "",
|
||||
"reminderTime": "",
|
||||
"frequency": {
|
||||
"type": "daily"
|
||||
},
|
||||
"streak": {
|
||||
"current": 0,
|
||||
"best": 0,
|
||||
"lastCheckIn": null
|
||||
},
|
||||
"lives": 3,
|
||||
"completions": [],
|
||||
"createdAt": "2026-04-21T13:40:27.435565",
|
||||
"updatedAt": "2026-04-21T13:40:27.435565"
|
||||
},
|
||||
{
|
||||
"id": "24fc969a-6b4c-42ab-822a-d3183d0fc91b",
|
||||
"name": "Yoga practice",
|
||||
"category": "health",
|
||||
"color": "#8B5CF6",
|
||||
"icon": "heart",
|
||||
"priority": 50,
|
||||
"notes": "",
|
||||
"reminderTime": "",
|
||||
"frequency": {
|
||||
"type": "daily"
|
||||
},
|
||||
"streak": {
|
||||
"current": 0,
|
||||
"best": 0,
|
||||
"lastCheckIn": null
|
||||
},
|
||||
"lives": 0,
|
||||
"completions": [
|
||||
{
|
||||
"date": "2026-04-21",
|
||||
"type": "skip"
|
||||
},
|
||||
{
|
||||
"date": "2026-04-21",
|
||||
"type": "skip"
|
||||
},
|
||||
{
|
||||
"date": "2026-04-21",
|
||||
"type": "skip"
|
||||
}
|
||||
],
|
||||
"createdAt": "2026-04-21T13:40:27.944779",
|
||||
"updatedAt": "2026-04-21T13:40:27.949587"
|
||||
},
|
||||
{
|
||||
"id": "a3e13785-08c2-4866-a764-45451e8dfbba",
|
||||
"name": "Code review",
|
||||
"category": "work",
|
||||
"color": "#F59E0B",
|
||||
"icon": "code",
|
||||
"priority": 50,
|
||||
"notes": "",
|
||||
"reminderTime": "",
|
||||
"frequency": {
|
||||
"type": "specific_days",
|
||||
"days": [
|
||||
"monday",
|
||||
"wednesday"
|
||||
]
|
||||
},
|
||||
"streak": {
|
||||
"current": 0,
|
||||
"best": 0,
|
||||
"lastCheckIn": null
|
||||
},
|
||||
"lives": 3,
|
||||
"completions": [],
|
||||
"createdAt": "2026-04-21T13:40:28.453967",
|
||||
"updatedAt": "2026-04-21T13:40:28.457179"
|
||||
},
|
||||
{
|
||||
"id": "18eddd3f-c4f0-4023-ac68-6e3cd33ca04a",
|
||||
"name": "Guitar practice",
|
||||
"category": "personal",
|
||||
"color": "#EC4899",
|
||||
"icon": "music",
|
||||
"priority": 50,
|
||||
"notes": "",
|
||||
"reminderTime": "",
|
||||
"frequency": {
|
||||
"type": "daily"
|
||||
},
|
||||
"streak": {
|
||||
"current": 0,
|
||||
"best": 0,
|
||||
"lastCheckIn": null
|
||||
},
|
||||
"lives": 3,
|
||||
"completions": [],
|
||||
"createdAt": "2026-04-21T13:40:28.962515",
|
||||
"updatedAt": "2026-04-21T13:40:28.962515"
|
||||
},
|
||||
{
|
||||
"id": "8509c820-c187-4d7d-9f01-d754c7ff6bc3",
|
||||
"name": "Gym workout",
|
||||
"category": "health",
|
||||
"color": "#EF4444",
|
||||
"icon": "dumbbell",
|
||||
"priority": 50,
|
||||
"notes": "",
|
||||
"reminderTime": "",
|
||||
"frequency": {
|
||||
"type": "specific_days",
|
||||
"days": [
|
||||
"monday",
|
||||
"wednesday"
|
||||
]
|
||||
},
|
||||
"streak": {
|
||||
"current": 0,
|
||||
"best": 0,
|
||||
"lastCheckIn": null
|
||||
},
|
||||
"lives": 3,
|
||||
"completions": [],
|
||||
"createdAt": "2026-04-21T13:40:29.478868",
|
||||
"updatedAt": "2026-04-21T13:40:29.478868"
|
||||
},
|
||||
{
|
||||
"id": "e0961521-81f7-471f-b794-c42d2650a95b",
|
||||
"name": "Meditation",
|
||||
"category": "health",
|
||||
"color": "#10B981",
|
||||
"icon": "brain",
|
||||
"priority": 50,
|
||||
"notes": "",
|
||||
"reminderTime": "",
|
||||
"frequency": {
|
||||
"type": "daily"
|
||||
},
|
||||
"streak": {
|
||||
"current": 0,
|
||||
"best": 0,
|
||||
"lastCheckIn": null
|
||||
},
|
||||
"lives": 3,
|
||||
"completions": [],
|
||||
"createdAt": "2026-04-21T13:40:29.984484",
|
||||
"updatedAt": "2026-04-21T13:40:29.984484"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -690,6 +690,35 @@ class ProjectsHandlers:
|
||||
"""Dashboard planning sessions live in adapter='dashboard', channel=slug."""
|
||||
return ("dashboard", slug)
|
||||
|
||||
@staticmethod
|
||||
def _resolve_planning_key(slug: str) -> tuple[str, str]:
|
||||
"""Find the active session's (adapter, channel) for slug, regardless of
|
||||
where it was started. Falls back to ('dashboard', slug) if nothing
|
||||
matches — preserving prior behavior for the no-session case.
|
||||
|
||||
Picks the most-recently-updated entry when multiple exist.
|
||||
"""
|
||||
try:
|
||||
from src.planning_session import _load_planning_state # type: ignore
|
||||
except Exception:
|
||||
return ("dashboard", slug)
|
||||
try:
|
||||
all_state = _load_planning_state()
|
||||
except Exception:
|
||||
return ("dashboard", slug)
|
||||
|
||||
matches = [
|
||||
entry for entry in all_state.values()
|
||||
if (entry.get("slug") or "").lower() == slug.lower()
|
||||
]
|
||||
if not matches:
|
||||
return ("dashboard", slug)
|
||||
matches.sort(key=lambda e: e.get("updated_at") or "", reverse=True)
|
||||
best = matches[0]
|
||||
adapter = best.get("adapter") or "dashboard"
|
||||
channel = best.get("channel_id") or slug
|
||||
return (adapter, channel)
|
||||
|
||||
# ── POST /api/projects/<slug>/plan/start ──────────────────────
|
||||
def handle_plan_start(self, slug: str):
|
||||
if validate_slug(slug):
|
||||
@@ -793,7 +822,7 @@ class ProjectsHandlers:
|
||||
self.send_json({"error": "message required"}, 400)
|
||||
return
|
||||
|
||||
adapter, channel = self._planning_key(slug)
|
||||
adapter, channel = self._resolve_planning_key(slug)
|
||||
try:
|
||||
from src.planning_orchestrator import PlanningOrchestrator # type: ignore
|
||||
session, text, phase_ready = PlanningOrchestrator.respond(
|
||||
@@ -915,7 +944,7 @@ class ProjectsHandlers:
|
||||
if validate_slug(slug):
|
||||
self.send_json({"error": "invalid_slug"}, 400)
|
||||
return
|
||||
adapter, channel = self._planning_key(slug)
|
||||
adapter, channel = self._resolve_planning_key(slug)
|
||||
try:
|
||||
from src.planning_session import get_planning_state, clear_planning_state # type: ignore
|
||||
from src.planning_orchestrator import PlanningOrchestrator # type: ignore
|
||||
@@ -964,7 +993,7 @@ class ProjectsHandlers:
|
||||
if validate_slug(slug):
|
||||
self.send_json({"error": "invalid_slug"}, 400)
|
||||
return
|
||||
adapter, channel = self._planning_key(slug)
|
||||
adapter, channel = self._resolve_planning_key(slug)
|
||||
try:
|
||||
from src.planning_orchestrator import PlanningOrchestrator # type: ignore
|
||||
except Exception as exc:
|
||||
@@ -992,7 +1021,7 @@ class ProjectsHandlers:
|
||||
if validate_slug(slug):
|
||||
self.send_json({"error": "invalid_slug"}, 400)
|
||||
return
|
||||
adapter, channel = self._planning_key(slug)
|
||||
adapter, channel = self._resolve_planning_key(slug)
|
||||
try:
|
||||
from src.planning_orchestrator import PlanningOrchestrator # type: ignore
|
||||
session, text, completed = PlanningOrchestrator.advance(adapter, channel)
|
||||
|
||||
@@ -252,7 +252,17 @@
|
||||
// Browsers auto-follow 302, so a successful login surfaces
|
||||
// here as a 2xx (workspace.html) or an opaqueredirect.
|
||||
if (res.ok || res.type === 'opaqueredirect' || res.redirected) {
|
||||
var dest = res.url && res.redirected ? res.url : '/echo/workspace.html';
|
||||
// Redirect back to the page the user originally wanted,
|
||||
// passed as ?next= by the server. Validate it's a safe
|
||||
// relative /echo/ path to prevent open-redirect attacks.
|
||||
var params = new URLSearchParams(window.location.search);
|
||||
var next = params.get('next') || '';
|
||||
// The proxy strips /echo/ before Python, so `next` is
|
||||
// e.g. "/workspace.html". Re-add the /echo prefix for
|
||||
// the browser. Guard against open-redirect (no ://).
|
||||
var dest = (next && /^\/[^/]/.test(next) && next.indexOf('://') === -1)
|
||||
? '/echo' + next
|
||||
: '/echo/workspace.html';
|
||||
window.location.assign(dest);
|
||||
return;
|
||||
}
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,159 +0,0 @@
|
||||
/*
|
||||
* 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; }
|
||||
}
|
||||
@@ -13,7 +13,7 @@
|
||||
"ok": true,
|
||||
"status": "OK",
|
||||
"message": "Nicio modificare detectată",
|
||||
"lastCheck": "28 Apr 2026, 10:00",
|
||||
"lastCheck": "29 Apr 2026, 16:00",
|
||||
"changesCount": 0
|
||||
}
|
||||
}
|
||||
58
memory/kb/facebook/2026-04-29_julien-blanc-love-yourself.md
Normal file
58
memory/kb/facebook/2026-04-29_julien-blanc-love-yourself.md
Normal file
@@ -0,0 +1,58 @@
|
||||
# Love Yourself Even If They Don't
|
||||
|
||||
**Sursa:** https://www.facebook.com/share/r/1akfPJYvTw/
|
||||
**Data:** 2026-04-29
|
||||
**Creator:** Julien Blanc (@julienhimself)
|
||||
**Format:** Reel (~1 min)
|
||||
**Tags:** @coaching #self-love #self-esteem #social-approval #mindset
|
||||
|
||||
---
|
||||
|
||||
## TL;DR
|
||||
|
||||
Julien Blanc face un exercițiu pe stradă: îl întreabă pe un trecător care e artistul lui preferat. Răspunsul: Glenn Gould. Nimeni din grup nu știa cine e, apoi toți l-au criticat. Întrebarea lui Julien: "De ce mori pe colina asta pentru muzica lui Glenn Gould, dar nu faci același lucru pentru tine însuți?"
|
||||
|
||||
Mesajul central: stima de sine nu ar trebui să fluctueze în funcție de câți oameni te aprobă — la fel cum iubești un artist indiferent de opinia altora, poți să te iubești pe tine indiferent de opinia altora.
|
||||
|
||||
---
|
||||
|
||||
## Transcrierea
|
||||
|
||||
> What's your favorite band or singer of all time?
|
||||
> Just leave me with Gold playing Bach.
|
||||
> Did you understand what she said? No. Glenn Gould. Anyone know Glenn Gould? No.
|
||||
> Oh, is there one person who accepts it? Does it make your love for Glenn Gould less? No.
|
||||
> What if I'm like, that's the worst musician of all time. I hate them. Are you still going to listen to him?
|
||||
> He sucks. Yeah. I die on the hill.
|
||||
> Why were you down on the hill for him, but not you? We all shat on him, big time, diarrhea all over him.
|
||||
> That's my point, by the way. It's like, do you see it?
|
||||
> If you like something, you're like, hey, I like it. It doesn't matter if everyone hates it. I like it.
|
||||
> Why not that with you?
|
||||
> Here's me. Here's me. You all hate me? I like me.
|
||||
> Why does it change for you, depending on how many people like it, but not Glenn Gould?
|
||||
> I don't know. Yeah, you do. A part of you does.
|
||||
> Why not you? Why are you not like, I love me?
|
||||
> Why are you not as badass as his music?
|
||||
|
||||
---
|
||||
|
||||
## Puncte cheie
|
||||
|
||||
1. **Stima de sine condiționată vs necondiționată**: Majoritatea oamenilor își evaluează valoarea în funcție de câți oameni îi aprobă. Cu artiștii preferați nu fac asta — de ce nu aplică același standard la ei înșiși?
|
||||
|
||||
2. **"Die on the hill"**: Să fii dispus să aperi ceva (sau pe tine) chiar și când toată lumea e împotrivă. Asta nu înseamnă aroganță — înseamnă că valoarea ta nu e pusă la vot.
|
||||
|
||||
3. **Exercițiul mental**: Gândește-te la ceva ce iubești necondiționat (muzică, hobby, persoană). Acum aplică același nivel de loialitate față de tine însuți.
|
||||
|
||||
---
|
||||
|
||||
## Quote notabil
|
||||
|
||||
> "Why does it change for you, depending on how many people like it, but not Glenn Gould? Why are you not as badass as his music?"
|
||||
|
||||
---
|
||||
|
||||
## Idei acționabile
|
||||
|
||||
- Când simți că valoarea ta depinde de validarea externă, întreabă-te: "Aș renunța la Glenn Gould dacă toată lumea l-ar urî?" — dacă nu, de ce renunți la tine?
|
||||
- Practică "die on the hill" pentru tine: identifică 3 lucruri despre tine pe care le aperi indiferent de opinie
|
||||
@@ -1,5 +1,25 @@
|
||||
{
|
||||
"notes": [
|
||||
{
|
||||
"file": "notes-data/youtube/2026-04-29_ternary-models-local-ai.md",
|
||||
"title": "I Just Tried The Brand New Ternary Model And It's Great!",
|
||||
"date": "2026-04-29",
|
||||
"tags": [
|
||||
"local-ai",
|
||||
"llm",
|
||||
"ternary",
|
||||
"quantization"
|
||||
],
|
||||
"domains": [
|
||||
"work"
|
||||
],
|
||||
"types": [],
|
||||
"category": "youtube",
|
||||
"project": null,
|
||||
"subdir": null,
|
||||
"video": "",
|
||||
"tldr": "Prism ML a lansat primul model **ternary** viabil (Bonsai 8B Ternary), evoluția modelelor one-bit. Ternary folosește valori -1, 0, +1 în loc de -1/+1 (one-bit), ceea ce reduce eroarea de acuratețe la ..."
|
||||
},
|
||||
{
|
||||
"file": "notes-data/coaching/playlist-transe-meditatii.md",
|
||||
"title": "Playlist Transe Ghidate & Meditații",
|
||||
@@ -9017,12 +9037,27 @@
|
||||
"subdir": null,
|
||||
"video": "",
|
||||
"tldr": "Tutorial complet pentru a vorbi cu Claude Code prin telefon, folosind 3CX (sistem telefonic cloud gratuit) + un proiect GitHub custom. Setup-ul implică: 3CX cloud (gratuit, <10 useri), un voice server..."
|
||||
},
|
||||
{
|
||||
"id": "facebook/2026-04-29_julien-blanc-love-yourself",
|
||||
"title": "Love Yourself Even If They Don't — Julien Blanc",
|
||||
"path": "memory/kb/facebook/2026-04-29_julien-blanc-love-yourself.md",
|
||||
"date": "2026-04-29",
|
||||
"tags": [
|
||||
"coaching",
|
||||
"self-love",
|
||||
"self-esteem",
|
||||
"social-approval",
|
||||
"mindset"
|
||||
],
|
||||
"source": "facebook-reel",
|
||||
"creator": "Julien Blanc"
|
||||
}
|
||||
],
|
||||
"stats": {
|
||||
"total": 518,
|
||||
"total": 520,
|
||||
"by_domain": {
|
||||
"work": 163,
|
||||
"work": 164,
|
||||
"health": 98,
|
||||
"growth": 234,
|
||||
"sprijin": 39,
|
||||
@@ -9040,7 +9075,7 @@
|
||||
"reflectii": 3,
|
||||
"retete": 1,
|
||||
"tools": 7,
|
||||
"youtube": 105,
|
||||
"youtube": 106,
|
||||
"memory": 43
|
||||
}
|
||||
},
|
||||
@@ -9077,4 +9112,4 @@
|
||||
"youtube",
|
||||
"memory"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
49
memory/kb/youtube/2026-04-29_ternary-models-local-ai.md
Normal file
49
memory/kb/youtube/2026-04-29_ternary-models-local-ai.md
Normal file
@@ -0,0 +1,49 @@
|
||||
# I Just Tried The Brand New Ternary Model And It's Great!
|
||||
|
||||
**Sursa:** https://youtu.be/lDlkkDs43aw
|
||||
**Data:** 2026-04-29
|
||||
**Canal:** Anything LLM / Timothy Carbat
|
||||
**Durata:** ~25 min
|
||||
**Tags:** @work @tech #local-ai #llm #ternary #quantization
|
||||
|
||||
---
|
||||
|
||||
## TL;DR
|
||||
|
||||
Prism ML a lansat primul model **ternary** viabil (Bonsai 8B Ternary), evoluția modelelor one-bit. Ternary folosește valori -1, 0, +1 în loc de -1/+1 (one-bit), ceea ce reduce eroarea de acuratețe la aproape zero față de FP16, cu resurse de 7-8x mai mici. File size ~2GB, memorie RAM ~2GB pentru un model de inteligență 8B. Rulabil local pe orice hardware (CPU, GPU, Mac M-series) via o versiune custom de llama.cpp de la Prism ML.
|
||||
|
||||
---
|
||||
|
||||
## Puncte cheie
|
||||
|
||||
1. **One-bit vs Ternary**: One-bit = valori -1 sau +1 (adunare simplă, extrem de eficient). Ternary = valori -1, 0, +1 (1.58 biți efectivi) — mai precis, aproape la nivelul FP16.
|
||||
|
||||
2. **Benchmark-uri**: Ternary Bonsai 8B → 75.5 medie vs Qwen3 8B FP16 → 79.3. One-bit → 70. Gap mic față de modelul full, enorm față de quantizare clasică la 2-bit.
|
||||
|
||||
3. **Resurse**: Model FP16 8B = 16GB VRAM. Ternary 8B = ~2GB. De 7-8x mai mic, cu pierdere minimă de acuratețe.
|
||||
|
||||
4. **Instalare**: llama.cpp custom fork de la Prism ML (GitHub releases) + GGUF model de pe HuggingFace. Nu e one-click, necesită terminal, dar e simplu.
|
||||
|
||||
5. **Integrare Anything LLM**: Se configurează ca provider OpenAI generic cu `localhost:8080/v1`. Suportă tools (web search, SQL, Gmail, Google Calendar, documente).
|
||||
|
||||
6. **Limitare actuală**: Momentan doar până la 8B parametri. Dacă Prism ML antrenează un model 27B ternary, acesta ar putea rula pe telefon cu acuratețe completă — schimbă fundamental local AI.
|
||||
|
||||
7. **Viitor local AI**: Combinat cu context window improvements (turboquant), ~80% din taskurile zilnice de inferență pot fi făcute local, fără cloud.
|
||||
|
||||
---
|
||||
|
||||
## Quote-uri notabile
|
||||
|
||||
> "This is the future of local AI. Imagine being able to run Qwen3 27B with its full accuracy on your phone."
|
||||
|
||||
> "Benchmarks should be used as a useful gauge to just eyeball if a model is worth your time — the only way to know if a model is good is to download it."
|
||||
|
||||
> "We're saving on both sides of the puzzle and I really don't see how local models don't win."
|
||||
|
||||
---
|
||||
|
||||
## Idei acționabile
|
||||
|
||||
- [ ] Testează Ternary Bonsai 8B local (LXC Ollama 104 sau direct pe server) — file size ~2GB, compatibil cu llama.cpp custom
|
||||
- [ ] Urmărește Prism ML pentru modele >8B (27B ternary ar fi game-changer pentru Chatbot Maria sau asistență locală)
|
||||
- [ ] Evaluează înlocuirea unor apeluri cloud API cu model ternary local pentru taskuri repetitive (reducere costuri)
|
||||
@@ -1046,3 +1046,42 @@
|
||||
[2026-04-28 10:00:05] OK: SIT_FIN_AN_2025
|
||||
[2026-04-28 10:00:05] OK: DESCARCARE_DECLARATII
|
||||
[2026-04-28 10:00:05] === Monitor complete ===
|
||||
[2026-04-28 16:00:00] === Starting ANAF monitor v2.1 ===
|
||||
[2026-04-28 16:00:00] OK: D100
|
||||
[2026-04-28 16:00:00] OK: D101
|
||||
[2026-04-28 16:00:00] OK: D300
|
||||
[2026-04-28 16:00:00] OK: D390
|
||||
[2026-04-28 16:00:00] OK: D394
|
||||
[2026-04-28 16:00:00] OK: D205
|
||||
[2026-04-28 16:00:00] OK: D406
|
||||
[2026-04-28 16:00:01] OK: BILANT_2025
|
||||
[2026-04-28 16:00:01] OK: SIT_FIN_SEM_2025
|
||||
[2026-04-28 16:00:01] OK: SIT_FIN_AN_2025
|
||||
[2026-04-28 16:00:01] OK: DESCARCARE_DECLARATII
|
||||
[2026-04-28 16:00:01] === Monitor complete ===
|
||||
[2026-04-29 10:00:00] === Starting ANAF monitor v2.1 ===
|
||||
[2026-04-29 10:00:00] OK: D100
|
||||
[2026-04-29 10:00:00] OK: D101
|
||||
[2026-04-29 10:00:00] OK: D300
|
||||
[2026-04-29 10:00:00] OK: D390
|
||||
[2026-04-29 10:00:00] OK: D394
|
||||
[2026-04-29 10:00:00] OK: D205
|
||||
[2026-04-29 10:00:00] OK: D406
|
||||
[2026-04-29 10:00:01] OK: BILANT_2025
|
||||
[2026-04-29 10:00:01] OK: SIT_FIN_SEM_2025
|
||||
[2026-04-29 10:00:01] OK: SIT_FIN_AN_2025
|
||||
[2026-04-29 10:00:01] OK: DESCARCARE_DECLARATII
|
||||
[2026-04-29 10:00:01] === Monitor complete ===
|
||||
[2026-04-29 16:00:00] === Starting ANAF monitor v2.1 ===
|
||||
[2026-04-29 16:00:00] OK: D100
|
||||
[2026-04-29 16:00:00] OK: D101
|
||||
[2026-04-29 16:00:00] OK: D300
|
||||
[2026-04-29 16:00:00] OK: D390
|
||||
[2026-04-29 16:00:00] OK: D394
|
||||
[2026-04-29 16:00:00] OK: D205
|
||||
[2026-04-29 16:00:00] OK: D406
|
||||
[2026-04-29 16:00:01] OK: BILANT_2025
|
||||
[2026-04-29 16:00:01] OK: SIT_FIN_SEM_2025
|
||||
[2026-04-29 16:00:01] OK: SIT_FIN_AN_2025
|
||||
[2026-04-29 16:00:01] OK: DESCARCARE_DECLARATII
|
||||
[2026-04-29 16:00:01] === Monitor complete ===
|
||||
|
||||
Reference in New Issue
Block a user