diff --git a/AGENTS.md b/AGENTS.md index 88c8a97..32db01c 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -217,6 +217,14 @@ Când primesc un link YouTube: 3. Nota trebuie să conțină: TL;DR, pași concreți, comenzi, puncte cheie 4. Nu dau rezumate generice - surprind **esența** și **detaliile acționabile** 5. **DUPĂ SALVARE** rulez: `python3 ~/clawd/tools/update_notes_index.py` (actualizează index.json pentru kb.html) +6. **DEEP LINK:** Când dau link spre notă, folosesc formatul: + `https://moltbot.tailf7372d.ts.net/echo/files.html#kb/youtube/YYYY-MM-DD_titlu-slug.md` + (files.html deschide previzualizarea, notes.html nu) +7. **INSIGHTS:** Analizez nota și extrag idei aplicabile în `kb/insights/YYYY-MM-DD.md`: + - Fișier zilnic (ca memory/) + - Categorisez pe domeniu (@work, @health, @growth, @sprijin, @scout) + - Pentru fiecare idee: ce e, cum se aplică, propunere concretă + - **Link la sursă:** fiecare secțiune include deep link la nota originală ### 📦 Git Commits (~/clawd → gitea.romfast.ro/romfast/clawd) - **NU face commit automat** - întreabă-l pe Marius când să dau commit @@ -229,16 +237,20 @@ Când primesc un link YouTube: ### 📋 Task Tracking (OBLIGATORIU) Când primesc o acțiune/cerere de la Marius: 1. **React:** Reacționez cu 👍 la mesaj (WhatsApp/Discord) -2. **Start:** Adaug task în kanban (in-progress) cu `python3 kanban/update_task.py add "titlu"` +2. **Start:** Adaug task în kanban (in-progress) cu `python3 dashboard/update_task.py add "titlu"` 3. **Lucrez:** Execut cererea -4. **Done:** Marchez task-ul terminat cu `python3 kanban/update_task.py done ` +4. **Done:** Marchez task-ul terminat cu `python3 dashboard/update_task.py done ` Când se execută orice job cron: 1. **Start:** Creează task în kanban (Progress) cu numele job-ului 2. **Rulează:** Execută task-ul 3. **Done:** Mută task-ul în Done cu rezultatul -Astfel Marius poate vedea în https://moltbot.tailf7372d.ts.net/echo/ ce job-uri au rulat și când. +**TOATE acțiunile trebuie notate** - dashboard-ul arată statistici: +- Task-uri completate: azi / săptămâna / luna +- Număr de insights procesate + +Astfel Marius poate vedea în https://moltbot.tailf7372d.ts.net/echo/ ce s-a lucrat și când. **Things to check (rotate through these, 2-4 times per day):** - **Emails** - Any urgent unread messages? @@ -281,3 +293,13 @@ The goal: Be helpful without being annoying. Check in a few times a day, do usef ## Make It Yours This is a starting point. Add your own conventions, style, and rules as you figure out what works. + +### 📁 Reguli directoare (verifică .rules.json) +Când salvez în `kb/projects/`, verific dacă există `.rules.json`: +- Citesc `filenameRule` pentru cum să numesc fișierul +- Citesc `validTypes` pentru ce tipuri sunt valide +- Scriptul inferă automat tipul din filename dacă `inferTypeFromFilename: true` + +**Exemplu grup-sprijin:** +- Filename: `meditatie-nume-descriptiv.md` → automat @meditatie +- Tipuri valide: meditatie, exercitiu, reflectie, intrebare, fisa diff --git a/HEARTBEAT.md b/HEARTBEAT.md index d28417e..b64f098 100644 --- a/HEARTBEAT.md +++ b/HEARTBEAT.md @@ -17,6 +17,11 @@ ### 📦 Git status (seara) - [ ] Fișiere uncommitted? Dacă da, întreabă dacă fac commit. +### 📚 KB Index (la fiecare heartbeat) +- [ ] Verifică dacă vreun fișier din kb/ e mai nou decât kb/index.json +- [ ] Dacă da → `python3 tools/update_notes_index.py` +- [ ] Comandă rapidă: `find kb/ -name "*.md" -newer kb/index.json | head -1` + --- ## Tracking ultimele verificări diff --git a/TOOLS.md b/TOOLS.md index 620cb3e..848e81e 100644 --- a/TOOLS.md +++ b/TOOLS.md @@ -24,25 +24,26 @@ python3 tools/email_send.py "dest@email.com" "Subiect" "Corp mesaj" **Pentru orice altă adresă:** Citesc și raportez, aștept aprobare. -### Kanban & Web +### Dashboard & Web - **Task Board:** https://moltbot.tailf7372d.ts.net/echo/ -- **Notes:** https://moltbot.tailf7372d.ts.net/echo/notes.html +- **KB (Notes):** https://moltbot.tailf7372d.ts.net/echo/notes.html - **Files:** https://moltbot.tailf7372d.ts.net/echo/files.html -- **API:** `kanban/api.py` -- **Update task:** `python3 kanban/update_task.py` +- **API:** `dashboard/api.py` +- **Update task:** `python3 dashboard/update_task.py` **Reguli dashboard:** - Tab Activity afișează task-uri din tasks.json, sortate descrescător după timestamp - Când creez/completez task-uri, să am timestamp complet (ISO format cu oră) -### Notes (toate tipurile) -- **Folder:** `notes/` (subdirectoare: `youtube/`, `retete/`, etc.) +### KB - Knowledge Base (toate tipurile de conținut) +- **Folder:** `kb/` (subdirectoare: `youtube/`, `retete/`, `projects/`) - **Update index:** `python3 tools/update_notes_index.py` - **Pagina web:** https://moltbot.tailf7372d.ts.net/echo/notes.html - **Tags domeniu:** `@work`, `@health`, `@growth`, `@sprijin`, `@scout` +- **Tags tip:** `@project`, `@fisa`, `@exercitiu`, `@meditatie`, `@reflectie` -**IMPORTANT:** Când salvez orice notă (rețete, youtube, etc.), trebuie să: -1. Salvez în subdirectorul potrivit din `notes/` +**IMPORTANT:** Când salvez orice notă (rețete, youtube, proiecte, etc.), trebuie să: +1. Salvez în subdirectorul potrivit din `kb/` 2. Rulez `python3 tools/update_notes_index.py` pentru a actualiza indexul 3. Dau link-ul către pagina notes.html @@ -56,7 +57,7 @@ python3 tools/email_send.py "dest@email.com" "Subiect" "Corp mesaj" **TOOLS.md:** `agents/echo-work/TOOLS.md` -- **ANAF Monitor:** `anaf-monitor/monitor.py` - verificare la fiecare 6 ore +- **ANAF Monitor:** `tools/anaf-monitor/monitor.py` - verificare la fiecare 6 ore - Monitorizează: D100, D101, D200, D390, D406, situații financiare, E-Factura --- @@ -84,9 +85,11 @@ python3 tools/email_send.py "dest@email.com" "Subiect" "Corp mesaj" **TOOLS.md:** `agents/echo-sprijin/TOOLS.md` -- **Pagină dedicată:** https://moltbot.tailf7372d.ts.net/echo/grup-sprijin.html -- **Fișe activități:** `kanban/grup-sprijin/` -- **Template:** `kanban/grup-sprijin/template-fisa.md` +- **Pagină dedicată:** https://moltbot.tailf7372d.ts.net/echo/notes.html (filtrează @grup-sprijin) +- **Proiect:** `kb/projects/grup-sprijin/` +- **Biblioteca activități:** `kb/projects/grup-sprijin/biblioteca.json` +- **Fișe:** `kb/projects/grup-sprijin/fise/` +- **Template:** `kb/projects/grup-sprijin/template-fisa.md` --- diff --git a/USER.md b/USER.md index 5681985..7762f80 100644 --- a/USER.md +++ b/USER.md @@ -35,6 +35,16 @@ - **Preferă:** Să repare decât să construiască de la zero - **Preferă:** Mai multă muncă la preț bun de la clienți existenți +## Reguli pentru propuneri (OBLIGATORIU pentru Echo) + +- **80/20 STRICT:** Propun DOAR ce aduce impact mare cu efort mic +- **Simplitate:** NU complica fluxul, NU adăuga pași noi fără motiv solid +- **Integrare:** Orice propunere trebuie să se muleze pe fluxul CURENT +- **Judecată critică:** Filtrez EU mai întâi, nu propun tot ce citesc +- **Recomandare explicită:** La fiecare propunere zic: ✅ RECOMAND sau ⚠️ AȘTEPT sau ❌ NU RECOMAND + de ce +- **Context complet:** Timp, efort TU, impact flux, beneficiu concret +- **Anti-complexitate:** Dacă adaugă complexitate > beneficiu, NU propun + ## Interese și domenii - **Coaching & Comunicare:** NLP, Sleight of Mouth, comunicare nonviolentă diff --git a/agents/echo-growth/kanban b/agents/echo-growth/kanban index 6c93109..2551d65 120000 --- a/agents/echo-growth/kanban +++ b/agents/echo-growth/kanban @@ -1 +1 @@ -../../kanban \ No newline at end of file +../../dashboard \ No newline at end of file diff --git a/agents/echo-growth/notes b/agents/echo-growth/notes index e29c1ac..29f4031 120000 --- a/agents/echo-growth/notes +++ b/agents/echo-growth/notes @@ -1 +1 @@ -../../notes \ No newline at end of file +../../kb \ No newline at end of file diff --git a/agents/echo-growth/projects b/agents/echo-growth/projects index 8a37cd2..743f9ea 120000 --- a/agents/echo-growth/projects +++ b/agents/echo-growth/projects @@ -1 +1 @@ -../../projects \ No newline at end of file +../../kb/projects \ No newline at end of file diff --git a/agents/echo-health/USER.md b/agents/echo-health/USER.md index 7aa7dbc..9348685 100644 --- a/agents/echo-health/USER.md +++ b/agents/echo-health/USER.md @@ -3,6 +3,15 @@ - **Name:** Marius - **Timezone:** Europe/Bucharest (UTC+2/+3) +## Profil + +- 25 ani programator, principiul 80/20 +- E daltă nu ciocan (rafinează, simplifică) +- Îi place natura, jocul, SF/fantasy +- Lider cercetași +- Pattern: face munca, nu cere bani +- Caută cine vrea să fie (avatarul ideal) + ## Sănătate ### Condiții curente @@ -22,11 +31,37 @@ - **Post negru** - practica, efecte, planificare - Abordări holistice, legătura minte-corp -### Preferințe +## Filosofie & Spiritualitate -- Discuții deschise despre alternative, fără a înlocui medicina convențională -- Tracking și pattern-uri mai mult decât sfaturi directe +### Stoicism (vrea să aprofundeze) +- **Marcus Aurelius** - Meditations (reflecție, auto-disciplină) +- **Seneca** - Letters from a Stoic (practică zilnică, moarte, timp) +- **Epictetus** - Enchiridion, Discourses (ce controlăm vs ce nu) +- **Ryan Holiday** - stoicism modern aplicat + +### Poeți & Mistici +- **Rumi, Hafiz** - poeți sufi persani (iubire, căutare interioară) +- **Kahlil Gibran** - The Prophet (viață, relații, muncă) +- **Thich Nhat Hanh** - Zen, mindfulness, prezență +- **Lao Tzu** - Tao Te Ching (wu wei, flux natural) + +### Gânditori moderni +- **James Clear** - Atomic Habits, sisteme vs obiective +- **Naval Ravikant** - filosofie pentru antreprenori +- **Alan Watts** - filosofie estică pentru occidentali + +### Psihologie & Dezvoltare +- **NLP** - reframing, Sleight of Mouth +- **Personocrație** - autenticitate +- **Comunicare nonviolentă** - nevoi, empatie + +## Preferințe mesaje + +- Varietate din TOATE domeniile, nu doar sănătate fizică +- Perspectiva: sănătate, spiritualitate, igienă mentală/emoțională +- Surse variate, nu doar Rumi/NMG/Martel +- Concret și aplicat, nu abstract - Validare, nu alarmism --- -*Updated: 2026-01-30* +*Updated: 2026-01-31* diff --git a/agents/echo-health/kanban b/agents/echo-health/kanban index 6c93109..2551d65 120000 --- a/agents/echo-health/kanban +++ b/agents/echo-health/kanban @@ -1 +1 @@ -../../kanban \ No newline at end of file +../../dashboard \ No newline at end of file diff --git a/agents/echo-health/notes b/agents/echo-health/notes index e29c1ac..29f4031 120000 --- a/agents/echo-health/notes +++ b/agents/echo-health/notes @@ -1 +1 @@ -../../notes \ No newline at end of file +../../kb \ No newline at end of file diff --git a/agents/echo-health/projects b/agents/echo-health/projects index 8a37cd2..743f9ea 120000 --- a/agents/echo-health/projects +++ b/agents/echo-health/projects @@ -1 +1 @@ -../../projects \ No newline at end of file +../../kb/projects \ No newline at end of file diff --git a/agents/echo-scout/kanban b/agents/echo-scout/kanban index 6c93109..2551d65 120000 --- a/agents/echo-scout/kanban +++ b/agents/echo-scout/kanban @@ -1 +1 @@ -../../kanban \ No newline at end of file +../../dashboard \ No newline at end of file diff --git a/agents/echo-scout/notes b/agents/echo-scout/notes index e29c1ac..29f4031 120000 --- a/agents/echo-scout/notes +++ b/agents/echo-scout/notes @@ -1 +1 @@ -../../notes \ No newline at end of file +../../kb \ No newline at end of file diff --git a/agents/echo-scout/projects b/agents/echo-scout/projects index 8a37cd2..743f9ea 120000 --- a/agents/echo-scout/projects +++ b/agents/echo-scout/projects @@ -1 +1 @@ -../../projects \ No newline at end of file +../../kb/projects \ No newline at end of file diff --git a/agents/echo-sprijin/kanban b/agents/echo-sprijin/kanban index 6c93109..2551d65 120000 --- a/agents/echo-sprijin/kanban +++ b/agents/echo-sprijin/kanban @@ -1 +1 @@ -../../kanban \ No newline at end of file +../../dashboard \ No newline at end of file diff --git a/agents/echo-sprijin/notes b/agents/echo-sprijin/notes index e29c1ac..29f4031 120000 --- a/agents/echo-sprijin/notes +++ b/agents/echo-sprijin/notes @@ -1 +1 @@ -../../notes \ No newline at end of file +../../kb \ No newline at end of file diff --git a/agents/echo-sprijin/projects b/agents/echo-sprijin/projects index 8a37cd2..743f9ea 120000 --- a/agents/echo-sprijin/projects +++ b/agents/echo-sprijin/projects @@ -1 +1 @@ -../../projects \ No newline at end of file +../../kb/projects \ No newline at end of file diff --git a/agents/echo-work/kanban b/agents/echo-work/kanban index 6c93109..2551d65 120000 --- a/agents/echo-work/kanban +++ b/agents/echo-work/kanban @@ -1 +1 @@ -../../kanban \ No newline at end of file +../../dashboard \ No newline at end of file diff --git a/agents/echo-work/notes b/agents/echo-work/notes index e29c1ac..29f4031 120000 --- a/agents/echo-work/notes +++ b/agents/echo-work/notes @@ -1 +1 @@ -../../notes \ No newline at end of file +../../kb \ No newline at end of file diff --git a/agents/echo-work/projects b/agents/echo-work/projects index 8a37cd2..743f9ea 120000 --- a/agents/echo-work/projects +++ b/agents/echo-work/projects @@ -1 +1 @@ -../../projects \ No newline at end of file +../../kb/projects \ No newline at end of file diff --git a/kanban/api.py b/dashboard/api.py similarity index 75% rename from kanban/api.py rename to dashboard/api.py index 1f2494e..c5e8fc3 100644 --- a/kanban/api.py +++ b/dashboard/api.py @@ -16,8 +16,8 @@ from pathlib import Path BASE_DIR = Path(__file__).parent.parent TOOLS_DIR = BASE_DIR / 'tools' -NOTES_DIR = BASE_DIR / 'notes' / 'youtube' -KANBAN_DIR = BASE_DIR / 'kanban' +NOTES_DIR = BASE_DIR / 'kb' / 'youtube' +KANBAN_DIR = BASE_DIR / 'dashboard' class TaskBoardHandler(SimpleHTTPRequestHandler): @@ -26,9 +26,44 @@ class TaskBoardHandler(SimpleHTTPRequestHandler): self.handle_youtube() elif self.path == '/api/files': self.handle_files_post() + elif self.path == '/api/refresh-index': + self.handle_refresh_index() else: self.send_error(404) + def handle_refresh_index(self): + """Regenerate kb/index.json""" + try: + script = TOOLS_DIR / 'update_notes_index.py' + result = subprocess.run( + [sys.executable, str(script)], + capture_output=True, + text=True, + timeout=30 + ) + + if result.returncode == 0: + # Parse output for stats + output = result.stdout + total_match = re.search(r'with (\d+) notes', output) + total = int(total_match.group(1)) if total_match else 0 + + self.send_json({ + 'success': True, + 'message': f'Index regenerat cu {total} notițe', + 'total': total, + 'output': output + }) + else: + self.send_json({ + 'success': False, + 'error': result.stderr or 'Unknown error' + }, 500) + except subprocess.TimeoutExpired: + self.send_json({'success': False, 'error': 'Timeout'}, 500) + except Exception as e: + self.send_json({'success': False, 'error': str(e)}, 500) + def handle_files_post(self): """Save file content.""" try: @@ -63,8 +98,10 @@ class TaskBoardHandler(SimpleHTTPRequestHandler): def do_GET(self): if self.path == '/api/status': self.send_json({'status': 'ok', 'time': datetime.now().isoformat()}) - elif self.path == '/api/git': + elif self.path == '/api/git' or self.path.startswith('/api/git?'): self.handle_git_status() + elif self.path == '/api/agents' or self.path.startswith('/api/agents?'): + self.handle_agents_status() elif self.path.startswith('/api/files'): self.handle_files_get() elif self.path.startswith('/api/'): @@ -129,6 +166,55 @@ class TaskBoardHandler(SimpleHTTPRequestHandler): except Exception as e: self.send_json({'error': str(e)}, 500) + def handle_agents_status(self): + """Get agents status - fast version reading session files directly.""" + try: + # Define known agents + agents_config = [ + {'id': 'echo', 'name': 'Echo', 'emoji': '🌀'}, + {'id': 'echo-work', 'name': 'Work', 'emoji': '⚡'}, + {'id': 'echo-health', 'name': 'Health', 'emoji': '❤️'}, + {'id': 'echo-growth', 'name': 'Growth', 'emoji': '🪜'}, + {'id': 'echo-sprijin', 'name': 'Sprijin', 'emoji': '⭕'}, + {'id': 'echo-scout', 'name': 'Scout', 'emoji': '⚜️'}, + ] + + # Check active sessions by reading session files directly (fast) + active_agents = set() + sessions_base = Path.home() / '.clawdbot' / 'agents' + + if sessions_base.exists(): + for agent_dir in sessions_base.iterdir(): + if agent_dir.is_dir(): + sessions_file = agent_dir / 'sessions' / 'sessions.json' + if sessions_file.exists(): + try: + data = json.loads(sessions_file.read_text()) + # sessions.json is an object with session keys + now = datetime.now().timestamp() * 1000 + for key, sess in data.items(): + if isinstance(sess, dict): + last_active = sess.get('updatedAt', 0) + if now - last_active < 30 * 60 * 1000: # 30 min + active_agents.add(agent_dir.name) + break + except: + pass + + # Build response + agents = [] + for cfg in agents_config: + agents.append({ + 'id': cfg['id'], + 'name': cfg['name'], + 'emoji': cfg['emoji'], + 'active': cfg['id'] in active_agents + }) + + self.send_json({'agents': agents}) + except Exception as e: + self.send_json({'error': str(e)}, 500) + def handle_files_get(self): """List files or get file content.""" from urllib.parse import urlparse, parse_qs diff --git a/kanban/archive/tasks-2026-01.json b/dashboard/archive/tasks-2026-01.json similarity index 100% rename from kanban/archive/tasks-2026-01.json rename to dashboard/archive/tasks-2026-01.json diff --git a/kanban/archive_tasks.py b/dashboard/archive_tasks.py similarity index 100% rename from kanban/archive_tasks.py rename to dashboard/archive_tasks.py diff --git a/kanban/common.css b/dashboard/common.css similarity index 100% rename from kanban/common.css rename to dashboard/common.css diff --git a/dashboard/conversations b/dashboard/conversations new file mode 120000 index 0000000..b633ece --- /dev/null +++ b/dashboard/conversations @@ -0,0 +1 @@ +../conversations \ No newline at end of file diff --git a/kanban/echo-taskboard.service b/dashboard/echo-taskboard.service similarity index 100% rename from kanban/echo-taskboard.service rename to dashboard/echo-taskboard.service diff --git a/kanban/files.html b/dashboard/files.html similarity index 97% rename from kanban/files.html rename to dashboard/files.html index 43f3e61..cc6ff0c 100644 --- a/kanban/files.html +++ b/dashboard/files.html @@ -330,16 +330,12 @@ - Notes + KB Files - - - Grup - @@ -583,9 +579,16 @@ const isMarkdown = path.endsWith('.md'); document.getElementById('previewBtn').style.display = isMarkdown ? 'flex' : 'none'; - // Reset preview state - document.getElementById('editorBody').classList.remove('preview-active'); - document.getElementById('previewBtn').classList.remove('active'); + // Auto-activate preview for markdown files + if (isMarkdown) { + const preview = document.getElementById('markdownPreview'); + preview.innerHTML = marked.parse(data.content); + document.getElementById('editorBody').classList.add('preview-active'); + document.getElementById('previewBtn').classList.add('active'); + } else { + document.getElementById('editorBody').classList.remove('preview-active'); + document.getElementById('previewBtn').classList.remove('active'); + } if (data.truncated) { setStatus('Fișier trunchiat', 'error'); diff --git a/kanban/grup-sprijin.html b/dashboard/grup-sprijin.html similarity index 100% rename from kanban/grup-sprijin.html rename to dashboard/grup-sprijin.html diff --git a/kanban/index.html b/dashboard/index.html similarity index 88% rename from kanban/index.html rename to dashboard/index.html index 0968bac..c8d7c67 100644 --- a/kanban/index.html +++ b/dashboard/index.html @@ -14,6 +14,61 @@ padding: var(--space-5); } + /* Stats Summary */ + .stats-summary { + display: grid; + grid-template-columns: repeat(4, 1fr); + gap: var(--space-3); + margin-bottom: var(--space-4); + } + + @media (max-width: 768px) { + .stats-summary { + grid-template-columns: repeat(2, 1fr); + } + } + + .stat-card { + display: flex; + align-items: center; + gap: var(--space-3); + padding: var(--space-4); + background: var(--bg-surface); + border: 1px solid var(--border); + border-radius: var(--radius-lg); + } + + .stat-icon { + width: 40px; + height: 40px; + display: flex; + align-items: center; + justify-content: center; + background: var(--accent-subtle); + border-radius: var(--radius-md); + color: var(--accent); + } + + .stat-icon svg { + width: 20px; + height: 20px; + } + + .stat-content { + flex: 1; + } + + .stat-value { + font-size: var(--text-xl); + font-weight: 700; + color: var(--text-primary); + } + + .stat-label { + font-size: var(--text-xs); + color: var(--text-muted); + } + .page-header { margin-bottom: var(--space-4); } @@ -154,6 +209,33 @@ color: #818cf8; } + .status-section-icon.agents { + background: rgba(168, 85, 247, 0.15); + color: #a855f7; + } + + .agents-grid { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); + gap: var(--space-2); + } + + .agent-chip { + display: flex; + align-items: center; + gap: var(--space-2); + padding: var(--space-2) var(--space-3); + background: var(--bg-elevated); + border-radius: var(--radius-md); + font-size: var(--text-xs); + } + + .agent-chip .emoji { font-size: 14px; } + .agent-chip .name { font-weight: 500; color: var(--text-primary); } + .agent-chip .status { color: var(--text-muted); } + .agent-chip.active { background: rgba(34, 197, 94, 0.1); border: 1px solid rgba(34, 197, 94, 0.3); } + .agent-chip.active .status { color: #22c55e; } + .status-section-info { flex: 1; min-width: 0; @@ -794,16 +876,12 @@ - Notes + KB Files - - - Grup - @@ -894,6 +972,39 @@ + + + + + +
+
+
+
+
0
+
Azi
+
+
+
+
+
+
0
+
Săptămâna
+
+
+
+
+
+
0
+
Luna
+
+
+
+
+
+
0
+
Insights
+
@@ -1140,7 +1251,7 @@ async function loadGitStatus() { try { - const response = await fetch('/api/git?' + Date.now()); + const response = await fetch('./api/git?' + Date.now()); if (!response.ok) throw new Error('API error'); const git = await response.json(); @@ -1270,6 +1381,42 @@ lucide.createIcons(); } + async function loadAgentsStatus() { + try { + const response = await fetch('./api/agents?' + Date.now()); + if (!response.ok) throw new Error('API error'); + const data = await response.json(); + + const agents = data.agents || []; + const activeCount = agents.filter(a => a.active).length; + + // Update badge + const badge = document.getElementById('agentsBadge'); + badge.textContent = `${activeCount}/${agents.length}`; + badge.className = 'status-badge ' + (activeCount > 0 ? 'ok' : 'warning'); + + // Update subtitle + const subtitle = document.getElementById('agentsSubtitle'); + const activeNames = agents.filter(a => a.active).map(a => a.name).join(', '); + subtitle.textContent = activeCount > 0 ? `Activi: ${activeNames}` : 'Niciun agent activ'; + + // Update grid + const grid = document.getElementById('agentsGrid'); + grid.innerHTML = agents.map(agent => ` +
+ ${agent.emoji || '🤖'} + ${agent.name} + ${agent.active ? '●' : '○'} +
+ `).join(''); + + } catch (e) { + console.log('Agents status error:', e); + document.getElementById('agentsBadge').textContent = '-'; + document.getElementById('agentsSubtitle').textContent = 'Nu se poate încărca'; + } + } + function updateStatusSummary() { const gitBadge = document.getElementById('gitBadge'); const anafBadge = document.getElementById('anafBadge'); @@ -1366,9 +1513,51 @@ function refreshActivity() { loadActivity(); + loadStats(); showToast('Activitate reîmprospătată'); } + async function loadStats() { + try { + // Load tasks + const tasksRes = await fetch('tasks.json'); + const tasksData = await tasksRes.json(); + + // Get done tasks + const doneColumn = tasksData.columns.find(c => c.id === 'done'); + const doneTasks = doneColumn ? doneColumn.tasks : []; + + const now = new Date(); + const todayStart = new Date(now.getFullYear(), now.getMonth(), now.getDate()); + const weekStart = new Date(todayStart); + weekStart.setDate(weekStart.getDate() - weekStart.getDay() + 1); // Monday + const monthStart = new Date(now.getFullYear(), now.getMonth(), 1); + + let today = 0, week = 0, month = 0; + + doneTasks.forEach(task => { + if (!task.completed) return; + const completed = new Date(task.completed); + if (completed >= todayStart) today++; + if (completed >= weekStart) week++; + if (completed >= monthStart) month++; + }); + + document.getElementById('statToday').textContent = today; + document.getElementById('statWeek').textContent = week; + document.getElementById('statMonth').textContent = month; + + // Count insights + const insightsRes = await fetch('/echo/api/files?path=kb/insights'); + if (insightsRes.ok) { + const insightsData = await insightsRes.json(); + document.getElementById('statInsights').textContent = insightsData.files ? insightsData.files.length : 0; + } + } catch (e) { + console.log('Stats load error:', e); + } + } + function renderActivity() { const body = document.getElementById('activityBody'); @@ -1644,6 +1833,7 @@ loadStatus(); loadIssues(); loadActivity(); + loadStats(); diff --git a/kanban/issues.json b/dashboard/issues.json similarity index 100% rename from kanban/issues.json rename to dashboard/issues.json diff --git a/dashboard/memory b/dashboard/memory new file mode 120000 index 0000000..c45bdff --- /dev/null +++ b/dashboard/memory @@ -0,0 +1 @@ +../memory \ No newline at end of file diff --git a/dashboard/notes-data b/dashboard/notes-data new file mode 120000 index 0000000..ad44af9 --- /dev/null +++ b/dashboard/notes-data @@ -0,0 +1 @@ +../kb \ No newline at end of file diff --git a/kanban/notes.html b/dashboard/notes.html similarity index 55% rename from kanban/notes.html rename to dashboard/notes.html index 89ba334..536503b 100644 --- a/kanban/notes.html +++ b/dashboard/notes.html @@ -3,7 +3,7 @@ - Echo · Notes + Echo · KB @@ -155,9 +155,39 @@ } .note-tags { - display: flex; - flex-wrap: wrap; - gap: var(--space-1); + display: inline; + line-height: 1.4; + } + + .note-tag { + font-size: var(--text-sm); + margin-right: 6px; + } + + .note-tag.domain { + color: #f97316; + } + + .note-tag.type { + color: #8b5cf6; + } + + .note-tag.tag { + color: #94a3b8; + } + + .note-tags-toggle { + color: #94a3b8; + cursor: pointer; + font-size: var(--text-sm); + } + + .note-tags-toggle:hover { + color: var(--text-primary); + } + + .note-tags-full { + color: #94a3b8; } /* Empty section */ @@ -287,74 +317,197 @@ .markdown-body strong { color: var(--text-primary); } - /* Tag filter pills */ - .tag-filter { - margin-bottom: var(--space-5); + /* Filter bar with pills */ + .filter-bar { + display: flex; + flex-wrap: wrap; + align-items: center; + gap: var(--space-2); + margin-bottom: var(--space-4); + padding: var(--space-3); + background: var(--bg-surface); + border-radius: var(--radius-lg); + border: 1px solid rgba(255, 255, 255, 0.1); } - .tag-filter-header { + [data-theme="light"] .filter-bar { + border-color: rgba(0, 0, 0, 0.1); + } + + .filter-separator { + color: var(--text-muted); + opacity: 0.3; + margin: 0 var(--space-1); + } + + .filter-group { + display: flex; + align-items: center; + gap: var(--space-1); + flex-wrap: wrap; + } + + .filter-pill { + display: inline-flex; + align-items: center; + gap: var(--space-1); + padding: var(--space-1) var(--space-2); + background: var(--bg-secondary); + border: 1px solid rgba(255, 255, 255, 0.15); + border-radius: var(--radius-full); + font-size: var(--text-sm); + color: var(--text-secondary); + cursor: pointer; + transition: all var(--transition-fast); + white-space: nowrap; + } + + [data-theme="light"] .filter-pill { + border-color: rgba(0, 0, 0, 0.1); + } + + .filter-pill:hover { + background: var(--bg-surface-hover); + border-color: var(--accent); + } + + .filter-pill.active { + background: var(--accent); + border-color: var(--accent); + color: white; + } + + .filter-pill.dimmed { + opacity: 0.4; + } + + .filter-pill.dimmed:hover { + opacity: 0.7; + } + + /* Category pills - teal */ + .filter-pill.category { + background: rgba(20, 184, 166, 0.15); + border-color: rgba(20, 184, 166, 0.4); + color: #14b8a6; + } + .filter-pill.category:hover { + background: rgba(20, 184, 166, 0.25); + } + .filter-pill.category.active { + background: #14b8a6; + color: white; + } + + /* Project pills - blue */ + .filter-pill.project { + background: rgba(59, 130, 246, 0.15); + border-color: rgba(59, 130, 246, 0.4); + color: #3b82f6; + } + .filter-pill.project:hover { + background: rgba(59, 130, 246, 0.25); + } + .filter-pill.project.active { + background: #3b82f6; + color: white; + } + + /* Domain pills - orange */ + .filter-pill.domain { + background: rgba(249, 115, 22, 0.15); + border-color: rgba(249, 115, 22, 0.4); + color: #f97316; + } + .filter-pill.domain:hover { + background: rgba(249, 115, 22, 0.25); + } + .filter-pill.domain.active { + background: #f97316; + color: white; + } + + /* Type pills - purple */ + .filter-pill.type { + background: rgba(139, 92, 246, 0.15); + border-color: rgba(139, 92, 246, 0.4); + color: #8b5cf6; + } + .filter-pill.type:hover { + background: rgba(139, 92, 246, 0.25); + } + .filter-pill.type.active { + background: #8b5cf6; + color: white; + } + + /* Tag pills - gray */ + .filter-pill.tag { + background: rgba(100, 116, 139, 0.15); + border-color: rgba(100, 116, 139, 0.4); + color: #94a3b8; + } + .filter-pill.tag:hover { + background: rgba(100, 116, 139, 0.25); + } + .filter-pill.tag.active { + background: #64748b; + color: white; + } + + .filter-pill-count { + font-size: var(--text-xs); + opacity: 0.7; + } + + .filter-actions { display: flex; align-items: center; gap: var(--space-2); - cursor: pointer; - user-select: none; - margin-bottom: var(--space-2); + margin-left: auto; } - .tag-filter-header svg { + .filter-btn { + padding: var(--space-2); + background: transparent; + border: none; + color: var(--text-muted); + cursor: pointer; + border-radius: var(--radius-md); + display: flex; + align-items: center; + justify-content: center; + } + + .filter-btn:hover { + background: var(--bg-surface-hover); + color: var(--text-primary); + } + + .filter-btn.clear:hover { + background: rgba(239, 68, 68, 0.2); + color: #ef4444; + } + + .filter-btn svg { width: 16px; height: 16px; + } + + .more-tags-toggle { color: var(--text-muted); - transition: transform var(--transition-fast); + font-size: var(--text-sm); + cursor: pointer; + padding: var(--space-1) var(--space-2); } - .tag-filter.collapsed .tag-filter-header svg { - transform: rotate(-90deg); + .more-tags-toggle:hover { + color: var(--text-primary); } - .tag-pills-more { - display: none; - margin-top: var(--space-2); - } - - .tag-pills-more.expanded { - display: flex; - flex-wrap: wrap; - gap: var(--space-2); - } - - /* More tags toggle button - same style as pills */ - .tag-pill.more-toggle { - background: rgba(100, 116, 139, 0.2); - border-color: rgba(100, 116, 139, 0.4); - color: var(--text-muted); - } - .tag-pill.more-toggle:hover { - background: rgba(100, 116, 139, 0.3); - } - .tag-pill.more-toggle.expanded { - background: rgba(100, 116, 139, 0.4); - } - - /* Dimmed pills - tags not in visible notes */ - .tag-pill.dimmed { - opacity: 0.35; - } - .tag-pill.dimmed:hover { - opacity: 0.6; - } - - .filter-count { - font-size: var(--text-xs); - color: var(--text-muted); - margin-left: var(--space-1); - } - - .tag-filter-label { - font-size: var(--text-xs); - color: var(--text-muted); - margin-bottom: var(--space-2); - display: block; + @keyframes spin { + from { transform: rotate(0deg); } + to { transform: rotate(360deg); } } .tag-pills { @@ -497,16 +650,12 @@ - Notes + KB Files - - - Grup - @@ -515,15 +664,29 @@
-
-
-
+
+
+ | +
+ | +
+ | +
+ +
+ + +
@@ -594,171 +757,267 @@ notesIndex = []; } } - let selectedTags = new Set(); + // Current filter state + let selectedFilters = { + category: null, + project: null, + domain: null, + type: null, + tags: new Set() + }; + let showAllTags = false; - // Extract all tags with counts (including domains and categories) - function getAllTags() { - const tagCounts = {}; - notesIndex.forEach(note => { - // Category tags (📁youtube, 📁retete) - if (note.category) { - const catTag = '📁' + note.category; - tagCounts[catTag] = (tagCounts[catTag] || 0) + 1; - } - // Domain tags (@work, @health, etc.) - if (note.domains) { - note.domains.forEach(domain => { - const domainTag = '@' + domain; - tagCounts[domainTag] = (tagCounts[domainTag] || 0) + 1; - }); - } - // Regular tags - note.tags.forEach(tag => { - tagCounts[tag] = (tagCounts[tag] || 0) + 1; - }); + // Get counts for each filter value + function getFilterCounts(filteredNotes = null) { + const notes = filteredNotes || notesIndex; + const counts = { + categories: {}, + projects: {}, + domains: {}, + types: {}, + tags: {} + }; + + notes.forEach(note => { + if (note.category) counts.categories[note.category] = (counts.categories[note.category] || 0) + 1; + if (note.project) counts.projects[note.project] = (counts.projects[note.project] || 0) + 1; + if (note.domains) note.domains.forEach(d => counts.domains[d] = (counts.domains[d] || 0) + 1); + if (note.types) note.types.forEach(t => counts.types[t] = (counts.types[t] || 0) + 1); + if (note.tags) note.tags.forEach(t => counts.tags[t] = (counts.tags[t] || 0) + 1); }); - // Sort: categories first (📁), then domains (@), then by count - return Object.entries(tagCounts) - .sort((a, b) => { - const aIsCat = a[0].startsWith('📁'); - const bIsCat = b[0].startsWith('📁'); - const aIsDomain = a[0].startsWith('@'); - const bIsDomain = b[0].startsWith('@'); - if (aIsCat && !bIsCat) return -1; - if (!aIsCat && bIsCat) return 1; - if (aIsDomain && !bIsDomain) return -1; - if (!aIsDomain && bIsDomain) return 1; - return b[1] - a[1]; - }) - .map(([tag, count]) => ({ tag, count })); + + return counts; } - // Render tag pills - function renderTagPills(visibleNotes = null) { - const mainContainer = document.getElementById('mainPills'); - const moreContainer = document.getElementById('tagPills'); - const tags = getAllTags(); + // Render filter pills + function renderFilterPills(filteredNotes = null) { + const counts = getFilterCounts(); + const visibleCounts = filteredNotes ? getFilterCounts(filteredNotes) : counts; - // Calculate which tags appear in visible notes - const visibleTags = new Set(); - if (visibleNotes && visibleNotes.length > 0) { - visibleNotes.forEach(note => { - note.tags.forEach(t => visibleTags.add(t)); - (note.domains || []).forEach(d => visibleTags.add('@' + d)); - if (note.category) visibleTags.add('📁' + note.category); - }); + // Categories + const catHtml = Object.entries(counts.categories) + .sort((a, b) => b[1] - a[1]) + .map(([cat, count]) => { + const isActive = selectedFilters.category === cat; + const isVisible = visibleCounts.categories[cat] > 0; + const dimmed = filteredNotes && !isVisible && !isActive ? 'dimmed' : ''; + return ` + 📁${cat} ${count} + `; + }).join(''); + document.getElementById('categoryPills').innerHTML = catHtml; + + // Projects (only show if category=projects or no category selected) + const showProjects = !selectedFilters.category || selectedFilters.category === 'projects'; + const projHtml = showProjects && Object.keys(counts.projects).length > 0 ? Object.entries(counts.projects) + .sort((a, b) => b[1] - a[1]) + .map(([proj, count]) => { + const isActive = selectedFilters.project === proj; + const isVisible = visibleCounts.projects[proj] > 0; + const dimmed = filteredNotes && !isVisible && !isActive ? 'dimmed' : ''; + return ` + 📂${proj} ${count} + `; + }).join('') : ''; + document.getElementById('projectPills').innerHTML = projHtml; + document.getElementById('sep1').style.display = projHtml ? '' : 'none'; + + // Domains (@work, @health, etc.) - orange + const domainHtml = Object.entries(counts.domains) + .sort((a, b) => b[1] - a[1]) + .map(([domain, count]) => { + const isActive = selectedFilters.domain === domain; + const isVisible = visibleCounts.domains[domain] > 0; + const dimmed = filteredNotes && !isVisible && !isActive ? 'dimmed' : ''; + return ` + @${domain} ${count} + `; + }).join(''); + + // Types (@meditatie, @exercitiu, etc.) + const typeHtml = Object.entries(counts.types) + .sort((a, b) => b[1] - a[1]) + .map(([type, count]) => { + const isActive = selectedFilters.type === type; + const isVisible = visibleCounts.types[type] > 0; + const dimmed = filteredNotes && !isVisible && !isActive ? 'dimmed' : ''; + return ` + @${type} ${count} + `; + }).join(''); + + // Combine domains and types in typePills + document.getElementById('typePills').innerHTML = domainHtml + typeHtml; + document.getElementById('sep2').style.display = (domainHtml || typeHtml) ? '' : 'none'; + + // Tags - collapsed by default, show only count + const tagEntries = Object.entries(counts.tags).sort((a, b) => b[1] - a[1]); + const activeTagsCount = selectedFilters.tags.size; + + let tagHtml = ''; + if (showAllTags) { + // Show all tags + tagHtml = tagEntries.map(([tag, count]) => { + const isActive = selectedFilters.tags.has(tag); + const isVisible = visibleCounts.tags[tag] > 0; + const dimmed = filteredNotes && !isVisible && !isActive ? 'dimmed' : ''; + return ` + #${tag} ${count} + `; + }).join(''); + } else if (activeTagsCount > 0) { + // Show only active tags + tagHtml = [...selectedFilters.tags].map(tag => { + const count = counts.tags[tag] || 0; + return ` + #${tag} ${count} + `; + }).join(''); } - const hasFilter = visibleNotes !== null; + document.getElementById('tagPills').innerHTML = tagHtml; + document.getElementById('sep3').style.display = (tagHtml || tagEntries.length > 0) ? '' : 'none'; - // Separate: categories + domains vs regular tags - const mainTags = tags.filter(({tag}) => tag.startsWith('📁') || tag.startsWith('@')); - const moreTags = tags.filter(({tag}) => !tag.startsWith('📁') && !tag.startsWith('@')); - - // Check if more section is expanded - const isExpanded = moreContainer.classList.contains('expanded'); - const activeMoreCount = [...selectedTags].filter(t => !t.startsWith('📁') && !t.startsWith('@')).length; - - // Render main pills (categories + domains) - let mainHtml = mainTags.map(({ tag, count }) => { - let pillClass = 'tag-pill'; - if (tag.startsWith('📁')) pillClass += ' category'; - else if (tag.startsWith('@')) pillClass += ' domain'; - if (selectedTags.has(tag)) pillClass += ' active'; - // Dim tags not in visible notes (unless it's already selected) - if (hasFilter && !visibleTags.has(tag) && !selectedTags.has(tag)) pillClass += ' dimmed'; - return ` - ${tag} (${count}) - `; - }).join(''); - - // Add "more tags" toggle button inline - if (moreTags.length > 0) { - const visibleMoreCount = moreTags.filter(({tag}) => visibleTags.has(tag)).length; - const moreLabel = activeMoreCount > 0 - ? `+${moreTags.length} tags (${activeMoreCount} active)` - : (hasFilter && visibleMoreCount > 0 ? `+${visibleMoreCount}/${moreTags.length} tags` : `+${moreTags.length} tags`); - mainHtml += ` - ${isExpanded ? '−' : '+'} ${moreLabel} - `; - } - - if (selectedTags.size > 0) { - mainHtml += ``; - } - mainContainer.innerHTML = mainHtml; - - // Render more pills (regular tags) - const moreHtml = moreTags.map(({ tag, count }) => { - let pillClass = 'tag-pill'; - if (selectedTags.has(tag)) pillClass += ' active'; - if (hasFilter && !visibleTags.has(tag) && !selectedTags.has(tag)) pillClass += ' dimmed'; - return ` - ${tag} (${count}) - `; - }).join(''); - moreContainer.innerHTML = moreHtml; - } - - // Toggle tag selection - function toggleTag(tag) { - if (selectedTags.has(tag)) { - selectedTags.delete(tag); + // More tags toggle + const moreToggle = document.getElementById('moreTagsToggle'); + if (tagEntries.length > 0) { + const hiddenCount = activeTagsCount > 0 ? tagEntries.length - activeTagsCount : tagEntries.length; + if (showAllTags) { + moreToggle.textContent = `-${hiddenCount} tags`; + } else { + moreToggle.textContent = `+${hiddenCount} tags`; + } + moreToggle.style.display = ''; } else { - selectedTags.add(tag); + moreToggle.style.display = 'none'; + } + + // Clear button + const hasFilters = selectedFilters.category || selectedFilters.project || + selectedFilters.domain || selectedFilters.type || selectedFilters.tags.size > 0; + document.getElementById('clearBtn').style.display = hasFilters ? '' : 'none'; + } + + // Toggle filter + function toggleFilter(filterType, value) { + if (filterType === 'tag') { + if (selectedFilters.tags.has(value)) { + selectedFilters.tags.delete(value); + } else { + selectedFilters.tags.add(value); + } + } else { + selectedFilters[filterType] = selectedFilters[filterType] === value ? null : value; + // Reset child filters when parent changes + if (filterType === 'category' && value !== 'projects') { + selectedFilters.project = null; + } } - renderTagPills(); filterNotes(); } - // Clear all tag filters - function clearTagFilters() { - selectedTags.clear(); - renderTagPills(); - filterNotes(); - } - - // Toggle more tags section + // Toggle more tags function toggleMoreTags() { - const moreContainer = document.getElementById('tagPills'); - moreContainer.classList.toggle('expanded'); - renderTagPills(lastFilteredNotes); + showAllTags = !showAllTags; + renderFilterPills(lastFilteredNotes); } - // Filter notes by search and tags + // Toggle tags in note card + function toggleNoteTags(noteId) { + const full = document.getElementById('tags_' + noteId); + const toggle = full.parentElement; + const count = toggle.querySelector('.note-tags-count'); + if (full.style.display === 'none') { + full.style.display = 'inline'; + count.style.display = 'none'; + } else { + full.style.display = 'none'; + count.style.display = 'inline'; + } + } + + // Clear all filters + function clearFilters() { + selectedFilters = { category: null, project: null, domain: null, type: null, tags: new Set() }; + showAllTags = false; + document.getElementById('searchInput').value = ''; + filterNotes(); + } + + // Refresh index from server + async function refreshIndex() { + const icon = document.getElementById('refreshIcon'); + if (icon) icon.style.animation = 'spin 1s linear infinite'; + + try { + const response = await fetch('api/refresh-index', { method: 'POST' }); + if (!response.ok) { + throw new Error(`HTTP ${response.status}`); + } + const data = await response.json(); + + if (data.success) { + await loadNotesIndex(); + filterNotes(); + lucide.createIcons(); + console.log('Index refreshed:', data.message); + } else { + console.error('Refresh failed:', data.error); + alert('Eroare: ' + (data.error || 'Unknown error')); + } + } catch (e) { + console.error('Refresh error:', e); + alert('Eroare la refresh: ' + e.message); + } finally { + if (icon) icon.style.animation = ''; + } + } + + // Filter notes function filterNotes() { const query = document.getElementById('searchInput').value.toLowerCase().trim(); - let filtered = notesIndex; - // Filter by selected tags (AND logic) - includes categories and domains - if (selectedTags.size > 0) { - filtered = filtered.filter(note => { - const allNoteTags = [ - ...note.tags, - ...(note.domains || []).map(d => '@' + d), - note.category ? '📁' + note.category : null - ].filter(Boolean); - return [...selectedTags].every(tag => allNoteTags.includes(tag)); + // Filter by category + if (selectedFilters.category) { + filtered = filtered.filter(n => n.category === selectedFilters.category); + } + + // Filter by project + if (selectedFilters.project) { + filtered = filtered.filter(n => n.project === selectedFilters.project); + } + + // Filter by domain (@work, @health, etc.) + if (selectedFilters.domain) { + filtered = filtered.filter(n => n.domains && n.domains.includes(selectedFilters.domain)); + } + + // Filter by type (@meditatie, @exercitiu, etc.) + if (selectedFilters.type) { + filtered = filtered.filter(n => n.types && n.types.includes(selectedFilters.type)); + } + + // Filter by tags (AND) + if (selectedFilters.tags.size > 0) { + filtered = filtered.filter(n => { + const noteTags = n.tags || []; + return [...selectedFilters.tags].every(t => noteTags.includes(t)); }); } - // Filter by search query + // Filter by search if (query) { - filtered = filtered.filter(note => { - const titleMatch = note.title.toLowerCase().includes(query); - const tagsMatch = note.tags.some(t => t.toLowerCase().includes(query)); - const contentMatch = (notesCache[note.file] || '').toLowerCase().includes(query); + filtered = filtered.filter(n => { + const titleMatch = n.title.toLowerCase().includes(query); + const tagsMatch = (n.tags || []).some(t => t.toLowerCase().includes(query)); + const contentMatch = (notesCache[n.file] || '').toLowerCase().includes(query); return titleMatch || tagsMatch || contentMatch; }); } - renderNotesAccordion(filtered); - - // Save filtered notes for tag pills lastFilteredNotes = filtered; - - // Update tag pills to show which tags are in visible notes - renderTagPills(filtered); + renderFilterPills(filtered); + renderNotesAccordion(filtered); } // Group notes by date category @@ -847,12 +1106,26 @@ } function renderNoteCard(note) { + // Domains (portocaliu), Types (mov), Tags colapsate cu expand + const tags = note.tags || []; + const noteId = note.file.replace(/[^a-zA-Z0-9]/g, '_'); + const tagsHtml = tags.length > 0 + ? ` + ${tags.length} tags + + ` + : ''; + + const allTags = [ + ...(note.domains || []).map(d => `${d}`), + ...(note.types || []).map(t => `${t}`), + tagsHtml + ].filter(Boolean).join(''); + return `
${note.title}
-
- ${note.tags.map(t => `${t}`).join('')} -
+
${allTags}
`; } @@ -878,7 +1151,7 @@ try { let content = notesCache[file]; if (!content) { - const response = await fetch(notesBasePath + file); + const response = await fetch(file); content = await response.text(); notesCache[file] = content; } @@ -897,7 +1170,7 @@ async function preloadNotes() { for (const note of notesIndex) { try { - const response = await fetch(notesBasePath + note.file); + const response = await fetch(note.file); notesCache[note.file] = await response.text(); } catch (e) { notesCache[note.file] = ''; @@ -929,8 +1202,9 @@ // Init - load index first, then render async function init() { await loadNotesIndex(); - renderTagPills(); - renderNotesAccordion(); + renderFilterPills(); + renderNotesAccordion(notesIndex); + lucide.createIcons(); preloadNotes(); checkHash(); } diff --git a/kanban/status.json b/dashboard/status.json similarity index 100% rename from kanban/status.json rename to dashboard/status.json diff --git a/kanban/swipe-nav.js b/dashboard/swipe-nav.js similarity index 100% rename from kanban/swipe-nav.js rename to dashboard/swipe-nav.js diff --git a/kanban/tasks.json b/dashboard/tasks.json similarity index 100% rename from kanban/tasks.json rename to dashboard/tasks.json diff --git a/kanban/update_task.py b/dashboard/update_task.py similarity index 100% rename from kanban/update_task.py rename to dashboard/update_task.py diff --git a/dashboard/youtube-notes b/dashboard/youtube-notes new file mode 120000 index 0000000..39e3448 --- /dev/null +++ b/dashboard/youtube-notes @@ -0,0 +1 @@ +../kb/youtube \ No newline at end of file diff --git a/grup-sprijin/index.json b/grup-sprijin/index.json deleted file mode 100644 index 7004179..0000000 --- a/grup-sprijin/index.json +++ /dev/null @@ -1,118 +0,0 @@ -[ - { - "id": "ancorare-emotii", - "title": "Exercițiu de ancorare a emoțiilor", - "type": "exercitiu", - "tags": [ - "NLP", - "ancorare", - "emotii", - "corp" - ], - "used": null, - "content": "Să simți o emoție pozitivă pe care ți-o dorești și apoi să faci exercițiul cu ancorarea emoției. Când vrei să simți liniște, satisfacție, bucurie, energie - să revină în corp.\n\nPași:\n1. Gândește-te la un moment în care ai simțit emoția dorită\n2. Simte-o în corp\n3. Ancoreaz-o (gest, cuvânt, imagine)\n4. Testează ancora" - }, - { - "id": "meditatie-demnitate", - "title": "Meditația cu demnitatea", - "type": "meditatie", - "tags": [ - "meditatie", - "demnitate", - "sine" - ], - "used": null, - "content": "Meditație despre demnitate personală.\n\n(De dezvoltat - Marius să adauge textul complet)" - }, - { - "id": "meditatie-eu-sunt-mai-mare", - "title": "Eu sunt mai mare decât gândurile și emoțiile mele", - "type": "meditatie", - "tags": [ - "meditatie", - "ganduri", - "emotii", - "distantare" - ], - "used": null, - "content": "Meditație: Eu sunt mai mare decât gândurile mele, mai mare decât emoțiile mele.\n\nIdee: Creezi distanță între tine și gânduri/emoții. Tu ești observatorul, nu gândul." - }, - { - "id": "meditatie-mindfulness", - "title": "Moment de mindfulness", - "type": "meditatie", - "tags": [ - "meditatie", - "mindfulness", - "prezent" - ], - "used": null, - "content": "Un moment de mindfulness - prezență în aici și acum.\n\n(De dezvoltat)" - }, - { - "id": "intrebare-bucurie-azi", - "title": "Ce ai făcut azi care ți-a adus bucurie?", - "type": "intrebare", - "tags": [ - "introspectie", - "bucurie", - "energie", - "recunostinta" - ], - "used": null, - "content": "Întrebări în secvență:\n1. Ce îți dorești să simți? (bucurie, energie, entuziasm, motivație)\n2. Când ai mai simțit asta?\n3. Ce ai făcut ASTĂZI care să îți aducă acea emoție?" - }, - { - "id": "intrebare-copil-interior", - "title": "Ce îți aducea bucurie când erai mic?", - "type": "intrebare", - "tags": [ - "introspectie", - "copilarie", - "pasiune", - "bucurie" - ], - "used": null, - "content": "Ce îți doreai să faci când erai mic? Ce îți aducea bucurie, entuziasm, satisfacție?\n\nCare era emoția? Ce poți să faci ACUM care să îți dea aceeași emoție?\n\nAdu-ți aminte de copilul care erai (poate mai ești și acum). Ce dorește să facă? Ce simțea? Când ai simțit acele emoții?" - }, - { - "id": "reflectie-barbati-energie", - "title": "Credințe despre bărbați și cerut ajutor", - "type": "reflectie", - "tags": [ - "credinte", - "masculin", - "ajutor", - "energie", - "vulnerabilitate" - ], - "used": null, - "content": "Credințe limitatoare:\n- Bărbații sunt puternici\n- Bărbații trebuie să facă totul singuri\n- Bărbații nu trebuie să ceară ajutor\n\nȘi pentru femei - când trebuie să facă totul singure, nu cer ajutor, se încarcă, trag, împing dintr-o energie masculină.\n\nE OK să faci, dar te oprește de la resursele de energie și creativitate.\n\nÎntrebare: Unde tragi singur când ai putea cere ajutor?" - }, - { - "id": "reflectie-oglinda", - "title": "Tot ce văd la tine am și eu în mine", - "type": "reflectie", - "tags": [ - "oglinda", - "proiectie", - "emotii", - "autocunoastere" - ], - "used": null, - "content": "Tot ce văd la tine am și eu în mine:\n- Sentimentul de vină, de rușine\n- Nu în aceleași situații\n- Furie, frustrare, jenă\n- Dar și bucurie\n\nCeilalți sunt oglinzi pentru noi." - }, - { - "id": "beneficiu-grup-siguranta", - "title": "Beneficiul grupului - siguranță", - "type": "reflectie", - "tags": [ - "grup", - "siguranta", - "energie", - "vulnerabilitate" - ], - "used": null, - "content": "Câtă energie consum să arăt ce trebuie?\n\nÎn grup nu mai este nevoie de energie să mențin scutul sus, să țin sub apă balonul.\n\nÎntr-un grup de sprijin, mă simt în siguranță, nu sunt judecat." - } -] \ No newline at end of file diff --git a/kanban/notes-data b/kanban/notes-data deleted file mode 120000 index 1a485a3..0000000 --- a/kanban/notes-data +++ /dev/null @@ -1 +0,0 @@ -../notes \ No newline at end of file diff --git a/kanban/youtube-notes b/kanban/youtube-notes deleted file mode 120000 index 293ced2..0000000 --- a/kanban/youtube-notes +++ /dev/null @@ -1 +0,0 @@ -../notes/youtube \ No newline at end of file diff --git a/kb/backlog.md b/kb/backlog.md new file mode 100644 index 0000000..4f96a71 --- /dev/null +++ b/kb/backlog.md @@ -0,0 +1,62 @@ +# Backlog - Propuneri pentru viitor + +**Tags:** @work @health @growth @sprijin @scout #backlog #propuneri + +Propuneri păstrate pentru viitor. Format: `[ ]` de făcut, `[x]` făcut, `[—]` renunțat. + +--- + +## ⚡ Urgent + Important + +*Gol momentan - se adaugă din insights când zici "azi prioritar"* + +--- + +## 📌 Important + +### @work +- [ ] Verificare securitate Clawdbot (port, trustedProxies) + +### @growth +- [ ] Exercițiu Priming în morning-coaching (3 recunoștințe) + +### @sprijin +- [ ] Fișă "blocare vs deblocare" cu exercițiu fiziologie + +--- + +## 💡 Nice-to-have + +### @work +- [ ] Template spec-driven development în kb/projects/ +- [ ] Job proactive coding noaptea (ora 23) +- [ ] Spellbook - prompt templates cu variabile + +### @health +- [ ] Checklist post negru (tranziție, clisme, apă) + +### @growth +- [ ] Dezvoltă personalitățile agenților (stil, nu doar funcțional) + +### @sprijin +- [ ] Întrebare "Ce moment greu s-a dovedit cadou?" +- [ ] Exercițiu "Pentru cine altcineva faci asta?" + +### @scout +- [ ] Activitate hero's journey pentru cercetași + +--- + +## ✅ Făcut + +*Se mută aici când completez* + +--- + +## ❌ Renunțat + +*Se mută aici când nu mai e relevant* + +--- + +*Ultima actualizare: 2026-01-31* diff --git a/kb/coaching/.rules.json b/kb/coaching/.rules.json new file mode 100644 index 0000000..8966abf --- /dev/null +++ b/kb/coaching/.rules.json @@ -0,0 +1,10 @@ +{ + "defaultDomains": ["health"], + "defaultTypes": ["coaching"], + "defaultTags": [], + "inferTypeFromFilename": true, + "filenameTypeMap": { + "dimineata": "coaching", + "seara": "reflectie" + } +} diff --git a/kb/index.json b/kb/index.json new file mode 100644 index 0000000..dc910fe --- /dev/null +++ b/kb/index.json @@ -0,0 +1,573 @@ +{ + "notes": [ + { + "file": "notes-data/insights/2026-01-31.md", + "title": "Insights 2026-01-31", + "date": "2026-01-31", + "tags": [ + "insights", + "propuneri" + ], + "domains": [ + "growth", + "health", + "work", + "sprijin", + "scout" + ], + "types": [], + "category": "insights", + "project": null, + "subdir": null, + "video": "", + "tldr": "*Scanare completă: 9 note YouTube | 2026-01-31*" + }, + { + "file": "notes-data/youtube/2026-01-31_tony-robbins-secret-extraordinary-life.md", + "title": "The Secret to an Extraordinary Life - Tony & Sage Robbins", + "date": "2026-01-31", + "tags": [], + "domains": [ + "growth" + ], + "types": [], + "category": "youtube", + "project": null, + "subdir": null, + "video": "", + "tldr": "Secretul unei vieți extraordinare nu e banii, poziția sau puterea - **e emoția**. Tony Robbins explică cum starea fizică, focusul și limbajul determină cum ne simțim. Pentru a te debloca: schimbă-ți c..." + }, + { + "file": "notes-data/projects/vending-master/README.md", + "title": "Proiect: Vending Master - Integrare Website → ROA", + "date": "2026-01-30", + "tags": [ + "vending-master", + "integrare" + ], + "domains": [ + "work" + ], + "types": [], + "category": "projects", + "project": "vending-master", + "subdir": null, + "video": "", + "tldr": "[conversations/2026-01-30-conversatie-completa.md](https://moltbot.tailf7372d.ts.net/echo/files.html#conversations/2026-01-30-conversatie-completa.md)" + }, + { + "file": "notes-data/projects/grup-sprijin/README.md", + "title": "Grup de Sprijin - Lideri Cercetași", + "date": "2026-01-30", + "tags": [ + "grup-sprijin" + ], + "domains": [ + "sprijin" + ], + "types": [], + "category": "projects", + "project": "grup-sprijin", + "subdir": null, + "video": "", + "tldr": "" + }, + { + "file": "notes-data/projects/grup-sprijin/fise/fisa-2026-02-05-ancorare-oglinda.md", + "title": "Fișă Întâlnire Grup Sprijin", + "date": "2026-01-30", + "tags": [ + "grup-sprijin" + ], + "domains": [ + "sprijin" + ], + "types": [ + "fisa" + ], + "category": "projects", + "project": "grup-sprijin", + "subdir": "fise", + "video": "", + "tldr": "" + }, + { + "file": "notes-data/projects/grup-sprijin/biblioteca/meditatie-mindfulness.md", + "title": "Moment de mindfulness", + "date": "2026-01-30", + "tags": [ + "mindfulness", + "prezent", + "grup-sprijin" + ], + "domains": [ + "sprijin" + ], + "types": [ + "meditatie" + ], + "category": "projects", + "project": "grup-sprijin", + "subdir": "biblioteca", + "video": "", + "tldr": "(De dezvoltat)" + }, + { + "file": "notes-data/projects/grup-sprijin/biblioteca/meditatie-eu-sunt-mai-mare.md", + "title": "Eu sunt mai mare decât gândurile și emoțiile mele", + "date": "2026-01-30", + "tags": [ + "ganduri", + "emotii", + "distantare", + "grup-sprijin" + ], + "domains": [ + "sprijin" + ], + "types": [ + "meditatie" + ], + "category": "projects", + "project": "grup-sprijin", + "subdir": "biblioteca", + "video": "", + "tldr": "Idee: Creezi distanță între tine și gânduri/emoții. Tu ești observatorul, nu gândul." + }, + { + "file": "notes-data/projects/grup-sprijin/biblioteca/meditatie-demnitate.md", + "title": "Meditația cu demnitatea", + "date": "2026-01-30", + "tags": [ + "demnitate", + "sine", + "grup-sprijin" + ], + "domains": [ + "sprijin" + ], + "types": [ + "meditatie" + ], + "category": "projects", + "project": "grup-sprijin", + "subdir": "biblioteca", + "video": "", + "tldr": "(De dezvoltat - Marius să adauge textul complet)" + }, + { + "file": "notes-data/projects/grup-sprijin/biblioteca/ancorare-emotii.md", + "title": "Exercițiu de ancorare a emoțiilor", + "date": "2026-01-30", + "tags": [ + "NLP", + "ancorare", + "emotii", + "corp", + "grup-sprijin" + ], + "domains": [ + "sprijin" + ], + "types": [ + "exercitiu" + ], + "category": "projects", + "project": "grup-sprijin", + "subdir": "biblioteca", + "video": "", + "tldr": "4. Testează ancora" + }, + { + "file": "notes-data/projects/grup-sprijin/biblioteca/intrebare-copil-interior.md", + "title": "Ce îți aducea bucurie când erai mic?", + "date": "2026-01-30", + "tags": [ + "introspectie", + "copilarie", + "pasiune", + "bucurie", + "grup-sprijin" + ], + "domains": [ + "sprijin" + ], + "types": [ + "intrebare" + ], + "category": "projects", + "project": "grup-sprijin", + "subdir": "biblioteca", + "video": "", + "tldr": "Adu-ți aminte de copilul care erai (poate mai ești și acum). Ce dorește să facă? Ce simțea? Când ai simțit acele emoții?" + }, + { + "file": "notes-data/projects/grup-sprijin/biblioteca/reflectie-oglinda.md", + "title": "Tot ce văd la tine am și eu în mine", + "date": "2026-01-30", + "tags": [ + "oglinda", + "proiectie", + "emotii", + "autocunoastere", + "grup-sprijin" + ], + "domains": [ + "sprijin" + ], + "types": [ + "reflectie" + ], + "category": "projects", + "project": "grup-sprijin", + "subdir": "biblioteca", + "video": "", + "tldr": "Ceilalți sunt oglinzi pentru noi." + }, + { + "file": "notes-data/projects/grup-sprijin/biblioteca/intrebare-bucurie-azi.md", + "title": "Ce ai făcut azi care ți-a adus bucurie?", + "date": "2026-01-30", + "tags": [ + "introspectie", + "bucurie", + "energie", + "recunostinta", + "grup-sprijin" + ], + "domains": [ + "sprijin" + ], + "types": [ + "intrebare" + ], + "category": "projects", + "project": "grup-sprijin", + "subdir": "biblioteca", + "video": "", + "tldr": "3. Ce ai făcut ASTĂZI care să îți aducă acea emoție?" + }, + { + "file": "notes-data/projects/grup-sprijin/biblioteca/beneficiu-grup-siguranta.md", + "title": "Beneficiul grupului - siguranță", + "date": "2026-01-30", + "tags": [ + "grup", + "siguranta", + "energie", + "vulnerabilitate", + "grup-sprijin" + ], + "domains": [ + "sprijin" + ], + "types": [ + "reflectie" + ], + "category": "projects", + "project": "grup-sprijin", + "subdir": "biblioteca", + "video": "", + "tldr": "Într-un grup de sprijin, mă simt în siguranță, nu sunt judecat." + }, + { + "file": "notes-data/projects/grup-sprijin/biblioteca/reflectie-barbati-energie.md", + "title": "Credințe despre bărbați și cerut ajutor", + "date": "2026-01-30", + "tags": [ + "credinte", + "masculin", + "ajutor", + "energie", + "vulnerabilitate", + "grup-sprijin" + ], + "domains": [ + "sprijin" + ], + "types": [ + "reflectie" + ], + "category": "projects", + "project": "grup-sprijin", + "subdir": "biblioteca", + "video": "", + "tldr": "Întrebare: Unde tragi singur când ai putea cere ajutor?" + }, + { + "file": "notes-data/retete/2026-01-30_ciorba-burta-falsa-cu-pui.md", + "title": "Ciorbă de Burtă Falsă cu Pui și Ciuperci Pleurotus", + "date": "2026-01-30", + "tags": [ + "ciorba", + "reteta", + "pleurotus", + "pui" + ], + "domains": [ + "health" + ], + "types": [], + "category": "retete", + "project": null, + "subdir": null, + "video": "", + "tldr": "- Se poate face și de post: fără carne, cu lapte vegetal în loc de smântână" + }, + { + "file": "notes-data/youtube/2026-01-30_claude-code-do-work-pattern.md", + "title": "The Most Powerful Claude Code Pattern I've Found", + "date": "2026-01-30", + "tags": [ + "claude-code", + "skills", + "workflow", + "automation", + "do-work" + ], + "domains": [ + "work" + ], + "types": [], + "category": "youtube", + "project": null, + "subdir": null, + "video": "https://youtu.be/I9-tdhxiH7w", + "tldr": "Un pattern puternic pentru Claude Code: **Do Work** - o coadă de task-uri pe care Claude le procesează automat, unul câte unul, în sub-agenți cu context curat. Ideea cheie: **construiește tool-uri pen..." + }, + { + "file": "notes-data/youtube/2026-01-30_clawdbot-5-use-cases.md", + "title": "5 Insane ClawdBot Use Cases You Need To Do Immediately", + "date": "2026-01-30", + "tags": [ + "clawdbot", + "automation", + "productivity", + "ai-assistant" + ], + "domains": [ + "work" + ], + "types": [], + "category": "youtube", + "project": null, + "subdir": null, + "video": "https://www.youtube.com/watch?v=b-l9sGh1-UY", + "tldr": "5 use case-uri pentru ClawdBot care îl transformă dintr-un simplu chatbot într-un asistent proactiv care lucrează pentru tine chiar și când dormi." + }, + { + "file": "notes-data/youtube/2026-01-30_clawdbot-personal-os-kitze.md", + "title": "How I Use Clawdbot to Run My Business and Life 24/7", + "date": "2026-01-30", + "tags": [ + "clawdbot", + "productivity", + "personas", + "automation" + ], + "domains": [ + "work", + "growth" + ], + "types": [], + "category": "youtube", + "project": null, + "subdir": null, + "video": "https://youtu.be/YRhGtHfs1Lw", + "tldr": "Kitze folosește **UN SINGUR gateway Clawdbot** cu **MULTIPLE PERSONAS** pe Telegram/Discord. Fiecare personă are:\n- Personalitate diferită (avatar, stil de vorbit)\n- Skills diferite (acces la tool-uri..." + }, + { + "file": "memory/2026-01-30.md", + "title": "2026-01-30", + "date": "2026-01-30", + "tags": [], + "domains": [], + "types": [ + "memory" + ], + "category": "memory", + "project": null, + "subdir": null, + "video": "", + "tldr": "- **Proactivitate activată**: Marius vrea să fiu proactiv - să propun automatizări, tools, să conectez punctele din discuții. Budget Claude Max $100/lună." + }, + { + "file": "conversations/2026-01-30-conversatie-completa.md", + "title": "2026-01-30 - Conversație completă dimineață", + "date": "2026-01-30", + "tags": [], + "domains": [], + "types": [ + "conversation" + ], + "category": "conversations", + "project": null, + "subdir": null, + "video": "", + "tldr": "6. **Nevoie:** Accountability - check-in-uri regulate ca să nu amâne." + }, + { + "file": "notes-data/youtube/2026-01-29_cloudflare-tunnel-localhost-public.md", + "title": "Cloudflare Tunnel: Make Localhost Public Without Port Forwarding", + "date": "2026-01-29", + "tags": [ + "cloudflare", + "tunnel", + "localhost", + "networking", + "devops" + ], + "domains": [ + "work" + ], + "types": [], + "category": "youtube", + "project": null, + "subdir": null, + "video": "https://youtu.be/etluT8UC-nw", + "tldr": "Cloudflare Tunnel permite expunerea unui server local (localhost) pe internet printr-un domeniu public, fără port forwarding, fără configurare router, fără expunerea IP-ului public. App-ul rămâne pe m..." + }, + { + "file": "notes-data/youtube/2026-01-29_gsd-framework-claude-code.md", + "title": "Forget Ralph Loops: The New GSD Framework for Claude Code", + "date": "2026-01-29", + "tags": [ + "claude-code", + "gsd", + "framework", + "sub-agents", + "automation" + ], + "domains": [ + "work" + ], + "types": [], + "category": "youtube", + "project": null, + "subdir": null, + "video": "https://www.youtube.com/watch?v=l94A53kIUB0", + "tldr": "GSD (Get Shit Done) este un framework open-source pentru Claude Code care orchestrează sub-agenți pentru a completa proiecte urmând spec-driven development. Rezolvă problema \"context bloat\" prin rular..." + }, + { + "file": "notes-data/youtube/2026-01-29_clawdbot-security-vulnerabilities.md", + "title": "It Got Worse (Clawdbot) - Security Vulnerabilities", + "date": "2026-01-29", + "tags": [ + "clawdbot", + "security", + "vulnerabilities", + "hacking" + ], + "domains": [ + "work" + ], + "types": [], + "category": "youtube", + "project": null, + "subdir": null, + "video": "https://youtu.be/rPAKq2oQVBs", + "tldr": "Video critic despre vulnerabilitățile de securitate ale Clawdbot - sute/mii de instanțe au fost compromise. Probleme principale: porturi default, parole lipsă, reverse proxy misconfigurat, skills mali..." + }, + { + "file": "notes-data/youtube/2026-01-29_greseli-post-apa.md", + "title": "Greșeli frecvente în timpul postului doar cu apă", + "date": "2026-01-29", + "tags": [ + "post", + "water-fasting", + "sănătate", + "detox" + ], + "domains": [ + "health" + ], + "types": [], + "category": "youtube", + "project": null, + "subdir": null, + "video": "https://youtu.be/4QjkI0sf64M", + "tldr": "Greșelile frecvente pe care le fac oamenii când țin post terapeutic cu apă și cum să le eviți. Puncte cheie: pregătire corectă, curățarea colonului, calitatea apei, și importanța scopului spiritual." + }, + { + "file": "notes-data/youtube/2026-01-29_remotion-skill-claude-code.md", + "title": "How people are generating videos with Claude Code (Remotion Skill)", + "date": "2026-01-29", + "tags": [ + "remotion", + "claude-code", + "video", + "automation" + ], + "domains": [ + "work" + ], + "types": [], + "category": "youtube", + "project": null, + "subdir": null, + "video": "https://youtu.be/7OR-L0AySn8", + "tldr": "Remotion Skill permite generarea de videouri programatic cu Claude Code. Funcționează prin React components → video export. Demo live: Claude creează animații YouTube (like, subscribe, cursor) doar di..." + }, + { + "file": "memory/2026-01-29.md", + "title": "2026-01-29 — Prima zi", + "date": "2026-01-29", + "tags": [], + "domains": [], + "types": [ + "memory" + ], + "category": "memory", + "project": null, + "subdir": null, + "video": "", + "tldr": "- [ ] Explora ce alte automatizări ar ajuta" + } + ], + "stats": { + "total": 26, + "by_domain": { + "work": 9, + "health": 3, + "growth": 3, + "sprijin": 12, + "scout": 1 + }, + "by_category": { + "coaching": 0, + "insights": 1, + "projects": 12, + "retete": 1, + "youtube": 9, + "memory": 2, + "conversations": 1 + } + }, + "domains": [ + "work", + "health", + "growth", + "sprijin", + "scout" + ], + "types": [ + "exercitiu", + "meditatie", + "reflectie", + "intrebare", + "fisa", + "project", + "memory", + "conversation", + "coaching" + ], + "categories": [ + "coaching", + "insights", + "projects", + "retete", + "youtube", + "memory", + "conversations" + ] +} \ No newline at end of file diff --git a/kb/insights/2026-01-31.md b/kb/insights/2026-01-31.md new file mode 100644 index 0000000..e3cb213 --- /dev/null +++ b/kb/insights/2026-01-31.md @@ -0,0 +1,59 @@ +# Insights 2026-01-31 + +**Tags:** @growth @health @work @sprijin @scout #insights #propuneri + +Idei extrase din note YouTube. Format: `[ ]` neprocesat, `[x]` făcut, `[→]` backlog, `[—]` skip. + +--- + +## @work - Productivitate & Automatizări + +- [ ] ⚡ Verificare securitate Clawdbot (port, trustedProxies) - [Security](https://moltbot.tailf7372d.ts.net/echo/files.html#kb/youtube/2026-01-29_clawdbot-security-vulnerabilities.md) +- [ ] 📌 Template spec-driven development în kb/projects/ - [GSD](https://moltbot.tailf7372d.ts.net/echo/files.html#kb/youtube/2026-01-29_gsd-framework-claude-code.md) +- [ ] 💡 Job proactive coding noaptea (ora 23) - [5 Use Cases](https://moltbot.tailf7372d.ts.net/echo/files.html#kb/youtube/2026-01-30_clawdbot-5-use-cases.md) +- [ ] 💡 Spellbook - prompt templates cu variabile - [Kitze](https://moltbot.tailf7372d.ts.net/echo/files.html#kb/youtube/2026-01-30_clawdbot-personal-os-kitze.md) + +--- + +## @health - Sănătate + +- [ ] 📌 Reminder "ridică-te, mergi 2 min" în respirații - [Tony Robbins](https://moltbot.tailf7372d.ts.net/echo/files.html#kb/youtube/2026-01-31_tony-robbins-secret-extraordinary-life.md) +- [ ] 💡 Checklist post negru (tranziție, clisme, apă) - [Post Apă](https://moltbot.tailf7372d.ts.net/echo/files.html#kb/youtube/2026-01-29_greseli-post-apa.md) + +--- + +## @growth - Dezvoltare personală + +- [ ] ⚡ Exercițiu Priming în morning-coaching (3 recunoștințe) - [Tony Robbins](https://moltbot.tailf7372d.ts.net/echo/files.html#kb/youtube/2026-01-31_tony-robbins-secret-extraordinary-life.md) +- [ ] 📌 Pattern Interrupt tehnica (fiziologie, focus, limbaj) - [Tony Robbins](https://moltbot.tailf7372d.ts.net/echo/files.html#kb/youtube/2026-01-31_tony-robbins-secret-extraordinary-life.md) +- [ ] 💡 Dezvoltă personalitățile agenților (stil, nu doar funcțional) - [Kitze](https://moltbot.tailf7372d.ts.net/echo/files.html#kb/youtube/2026-01-30_clawdbot-personal-os-kitze.md) + +--- + +## @sprijin - Grup sprijin + +- [ ] ⚡ Fișă "blocare vs deblocare" cu exercițiu fiziologie - [Tony Robbins](https://moltbot.tailf7372d.ts.net/echo/files.html#kb/youtube/2026-01-31_tony-robbins-secret-extraordinary-life.md) +- [ ] 📌 Întrebare "Ce moment greu s-a dovedit cadou?" - [Tony Robbins](https://moltbot.tailf7372d.ts.net/echo/files.html#kb/youtube/2026-01-31_tony-robbins-secret-extraordinary-life.md) +- [ ] 💡 Exercițiu "Pentru cine altcineva faci asta?" - [Post Apă](https://moltbot.tailf7372d.ts.net/echo/files.html#kb/youtube/2026-01-29_greseli-post-apa.md) + +--- + +## @scout - Cercetași + +- [ ] 💡 Activitate hero's journey pentru cercetași - [Tony Robbins](https://moltbot.tailf7372d.ts.net/echo/files.html#kb/youtube/2026-01-31_tony-robbins-secret-extraordinary-life.md) + +--- + +## Legendă + +- `[ ]` = neprocesat +- `[x]` = făcut +- `[→]` = mutat în backlog +- `[—]` = renunțat/skip +- ⚡ = urgent+important +- 📌 = important +- 💡 = nice-to-have + +--- + +*Scanare: 9 note YouTube | 2026-01-31* diff --git a/kb/projects/.rules.json b/kb/projects/.rules.json new file mode 100644 index 0000000..f3cc975 --- /dev/null +++ b/kb/projects/.rules.json @@ -0,0 +1,5 @@ +{ + "description": "Proiecte active", + "filenameRule": "Pentru proiecte cu tipuri, pune tipul în numele fișierului", + "inferTypeFromFilename": true +} diff --git a/kb/projects/grup-sprijin/.rules.json b/kb/projects/grup-sprijin/.rules.json new file mode 100644 index 0000000..59fbe5e --- /dev/null +++ b/kb/projects/grup-sprijin/.rules.json @@ -0,0 +1,15 @@ +{ + "description": "Proiect grup de sprijin - lideri cercetași", + "defaultDomains": ["sprijin"], + "defaultTags": ["grup-sprijin"], + "filenameRule": "Pune tipul în numele fișierului: meditatie-xxx.md, exercitiu-xxx.md, etc.", + "validTypes": ["meditatie", "exercitiu", "reflectie", "intrebare", "fisa"], + "inferTypeFromFilename": true, + "filenameTypeMap": { + "meditatie": "meditatie", + "exercitiu": "exercitiu", + "intrebare": "intrebare", + "reflectie": "reflectie", + "fisa": "fisa" + } +} diff --git a/projects/grup-sprijin-cercetasi.md b/kb/projects/grup-sprijin/README.md similarity index 100% rename from projects/grup-sprijin-cercetasi.md rename to kb/projects/grup-sprijin/README.md diff --git a/kanban/grup-sprijin/index.json b/kb/projects/grup-sprijin/biblioteca.json.bak similarity index 100% rename from kanban/grup-sprijin/index.json rename to kb/projects/grup-sprijin/biblioteca.json.bak diff --git a/kb/projects/grup-sprijin/biblioteca/ancorare-emotii.md b/kb/projects/grup-sprijin/biblioteca/ancorare-emotii.md new file mode 100644 index 0000000..38da264 --- /dev/null +++ b/kb/projects/grup-sprijin/biblioteca/ancorare-emotii.md @@ -0,0 +1,13 @@ +# Exercițiu de ancorare a emoțiilor + +**Tags:** @exercitiu @grup-sprijin #NLP #ancorare #emotii #corp + +--- + +Să simți o emoție pozitivă pe care ți-o dorești și apoi să faci exercițiul cu ancorarea emoției. Când vrei să simți liniște, satisfacție, bucurie, energie - să revină în corp. + +Pași: +1. Gândește-te la un moment în care ai simțit emoția dorită +2. Simte-o în corp +3. Ancoreaz-o (gest, cuvânt, imagine) +4. Testează ancora diff --git a/kb/projects/grup-sprijin/biblioteca/beneficiu-grup-siguranta.md b/kb/projects/grup-sprijin/biblioteca/beneficiu-grup-siguranta.md new file mode 100644 index 0000000..0c4efa8 --- /dev/null +++ b/kb/projects/grup-sprijin/biblioteca/beneficiu-grup-siguranta.md @@ -0,0 +1,11 @@ +# Beneficiul grupului - siguranță + +**Tags:** @reflectie @grup-sprijin #grup #siguranta #energie #vulnerabilitate + +--- + +Câtă energie consum să arăt ce trebuie? + +În grup nu mai este nevoie de energie să mențin scutul sus, să țin sub apă balonul. + +Într-un grup de sprijin, mă simt în siguranță, nu sunt judecat. diff --git a/kb/projects/grup-sprijin/biblioteca/intrebare-bucurie-azi.md b/kb/projects/grup-sprijin/biblioteca/intrebare-bucurie-azi.md new file mode 100644 index 0000000..a223211 --- /dev/null +++ b/kb/projects/grup-sprijin/biblioteca/intrebare-bucurie-azi.md @@ -0,0 +1,10 @@ +# Ce ai făcut azi care ți-a adus bucurie? + +**Tags:** @intrebare @grup-sprijin #introspectie #bucurie #energie #recunostinta + +--- + +Întrebări în secvență: +1. Ce îți dorești să simți? (bucurie, energie, entuziasm, motivație) +2. Când ai mai simțit asta? +3. Ce ai făcut ASTĂZI care să îți aducă acea emoție? diff --git a/kb/projects/grup-sprijin/biblioteca/intrebare-copil-interior.md b/kb/projects/grup-sprijin/biblioteca/intrebare-copil-interior.md new file mode 100644 index 0000000..bd44936 --- /dev/null +++ b/kb/projects/grup-sprijin/biblioteca/intrebare-copil-interior.md @@ -0,0 +1,11 @@ +# Ce îți aducea bucurie când erai mic? + +**Tags:** @intrebare @grup-sprijin #introspectie #copilarie #pasiune #bucurie + +--- + +Ce îți doreai să faci când erai mic? Ce îți aducea bucurie, entuziasm, satisfacție? + +Care era emoția? Ce poți să faci ACUM care să îți dea aceeași emoție? + +Adu-ți aminte de copilul care erai (poate mai ești și acum). Ce dorește să facă? Ce simțea? Când ai simțit acele emoții? diff --git a/kb/projects/grup-sprijin/biblioteca/meditatie-demnitate.md b/kb/projects/grup-sprijin/biblioteca/meditatie-demnitate.md new file mode 100644 index 0000000..6c6525c --- /dev/null +++ b/kb/projects/grup-sprijin/biblioteca/meditatie-demnitate.md @@ -0,0 +1,9 @@ +# Meditația cu demnitatea + +**Tags:** @meditatie @grup-sprijin #meditatie #demnitate #sine + +--- + +Meditație despre demnitate personală. + +(De dezvoltat - Marius să adauge textul complet) diff --git a/kb/projects/grup-sprijin/biblioteca/meditatie-eu-sunt-mai-mare.md b/kb/projects/grup-sprijin/biblioteca/meditatie-eu-sunt-mai-mare.md new file mode 100644 index 0000000..ead3bd7 --- /dev/null +++ b/kb/projects/grup-sprijin/biblioteca/meditatie-eu-sunt-mai-mare.md @@ -0,0 +1,9 @@ +# Eu sunt mai mare decât gândurile și emoțiile mele + +**Tags:** @meditatie @grup-sprijin #meditatie #ganduri #emotii #distantare + +--- + +Meditație: Eu sunt mai mare decât gândurile mele, mai mare decât emoțiile mele. + +Idee: Creezi distanță între tine și gânduri/emoții. Tu ești observatorul, nu gândul. diff --git a/kb/projects/grup-sprijin/biblioteca/meditatie-mindfulness.md b/kb/projects/grup-sprijin/biblioteca/meditatie-mindfulness.md new file mode 100644 index 0000000..6cb8e64 --- /dev/null +++ b/kb/projects/grup-sprijin/biblioteca/meditatie-mindfulness.md @@ -0,0 +1,9 @@ +# Moment de mindfulness + +**Tags:** @meditatie @grup-sprijin #meditatie #mindfulness #prezent + +--- + +Un moment de mindfulness - prezență în aici și acum. + +(De dezvoltat) diff --git a/kb/projects/grup-sprijin/biblioteca/reflectie-barbati-energie.md b/kb/projects/grup-sprijin/biblioteca/reflectie-barbati-energie.md new file mode 100644 index 0000000..589da40 --- /dev/null +++ b/kb/projects/grup-sprijin/biblioteca/reflectie-barbati-energie.md @@ -0,0 +1,16 @@ +# Credințe despre bărbați și cerut ajutor + +**Tags:** @reflectie @grup-sprijin #credinte #masculin #ajutor #energie #vulnerabilitate + +--- + +Credințe limitatoare: +- Bărbații sunt puternici +- Bărbații trebuie să facă totul singuri +- Bărbații nu trebuie să ceară ajutor + +Și pentru femei - când trebuie să facă totul singure, nu cer ajutor, se încarcă, trag, împing dintr-o energie masculină. + +E OK să faci, dar te oprește de la resursele de energie și creativitate. + +Întrebare: Unde tragi singur când ai putea cere ajutor? diff --git a/kb/projects/grup-sprijin/biblioteca/reflectie-oglinda.md b/kb/projects/grup-sprijin/biblioteca/reflectie-oglinda.md new file mode 100644 index 0000000..044c827 --- /dev/null +++ b/kb/projects/grup-sprijin/biblioteca/reflectie-oglinda.md @@ -0,0 +1,13 @@ +# Tot ce văd la tine am și eu în mine + +**Tags:** @reflectie @grup-sprijin #oglinda #proiectie #emotii #autocunoastere + +--- + +Tot ce văd la tine am și eu în mine: +- Sentimentul de vină, de rușine +- Nu în aceleași situații +- Furie, frustrare, jenă +- Dar și bucurie + +Ceilalți sunt oglinzi pentru noi. diff --git a/kanban/grup-sprijin/fisa-2026-02-05-ancorare-oglinda.md b/kb/projects/grup-sprijin/fise/fisa-2026-02-05-ancorare-oglinda.md similarity index 100% rename from kanban/grup-sprijin/fisa-2026-02-05-ancorare-oglinda.md rename to kb/projects/grup-sprijin/fise/fisa-2026-02-05-ancorare-oglinda.md diff --git a/kanban/grup-sprijin/template-fisa.md b/kb/projects/grup-sprijin/template-fisa.md similarity index 100% rename from kanban/grup-sprijin/template-fisa.md rename to kb/projects/grup-sprijin/template-fisa.md diff --git a/kb/projects/vending-master/.rules.json b/kb/projects/vending-master/.rules.json new file mode 100644 index 0000000..98d1a9c --- /dev/null +++ b/kb/projects/vending-master/.rules.json @@ -0,0 +1,5 @@ +{ + "description": "Proiect integrare Vending Master cu ROA", + "defaultDomains": ["work"], + "defaultTags": ["vending-master", "integrare"] +} diff --git a/projects/vending-master-integrare.md b/kb/projects/vending-master/README.md similarity index 100% rename from projects/vending-master-integrare.md rename to kb/projects/vending-master/README.md diff --git a/kb/retete/.rules.json b/kb/retete/.rules.json new file mode 100644 index 0000000..6a91cac --- /dev/null +++ b/kb/retete/.rules.json @@ -0,0 +1,5 @@ +{ + "defaultDomains": ["health"], + "defaultTypes": [], + "defaultTags": [] +} diff --git a/notes/retete/2026-01-30_ciorba-burta-falsa-cu-pui.md b/kb/retete/2026-01-30_ciorba-burta-falsa-cu-pui.md similarity index 100% rename from notes/retete/2026-01-30_ciorba-burta-falsa-cu-pui.md rename to kb/retete/2026-01-30_ciorba-burta-falsa-cu-pui.md diff --git a/kb/youtube/.rules.json b/kb/youtube/.rules.json new file mode 100644 index 0000000..bfda5cb --- /dev/null +++ b/kb/youtube/.rules.json @@ -0,0 +1,5 @@ +{ + "defaultDomains": [], + "defaultTypes": [], + "defaultTags": [] +} diff --git a/notes/youtube/2026-01-29_clawdbot-security-vulnerabilities.md b/kb/youtube/2026-01-29_clawdbot-security-vulnerabilities.md similarity index 100% rename from notes/youtube/2026-01-29_clawdbot-security-vulnerabilities.md rename to kb/youtube/2026-01-29_clawdbot-security-vulnerabilities.md diff --git a/notes/youtube/2026-01-29_cloudflare-tunnel-localhost-public.md b/kb/youtube/2026-01-29_cloudflare-tunnel-localhost-public.md similarity index 100% rename from notes/youtube/2026-01-29_cloudflare-tunnel-localhost-public.md rename to kb/youtube/2026-01-29_cloudflare-tunnel-localhost-public.md diff --git a/notes/youtube/2026-01-29_greseli-post-apa.md b/kb/youtube/2026-01-29_greseli-post-apa.md similarity index 100% rename from notes/youtube/2026-01-29_greseli-post-apa.md rename to kb/youtube/2026-01-29_greseli-post-apa.md diff --git a/notes/youtube/2026-01-29_gsd-framework-claude-code.md b/kb/youtube/2026-01-29_gsd-framework-claude-code.md similarity index 100% rename from notes/youtube/2026-01-29_gsd-framework-claude-code.md rename to kb/youtube/2026-01-29_gsd-framework-claude-code.md diff --git a/notes/youtube/2026-01-29_remotion-skill-claude-code.md b/kb/youtube/2026-01-29_remotion-skill-claude-code.md similarity index 100% rename from notes/youtube/2026-01-29_remotion-skill-claude-code.md rename to kb/youtube/2026-01-29_remotion-skill-claude-code.md diff --git a/notes/youtube/2026-01-30_claude-code-do-work-pattern.md b/kb/youtube/2026-01-30_claude-code-do-work-pattern.md similarity index 100% rename from notes/youtube/2026-01-30_claude-code-do-work-pattern.md rename to kb/youtube/2026-01-30_claude-code-do-work-pattern.md diff --git a/notes/youtube/2026-01-30_clawdbot-5-use-cases.md b/kb/youtube/2026-01-30_clawdbot-5-use-cases.md similarity index 100% rename from notes/youtube/2026-01-30_clawdbot-5-use-cases.md rename to kb/youtube/2026-01-30_clawdbot-5-use-cases.md diff --git a/notes/youtube/2026-01-30_clawdbot-personal-os-kitze.md b/kb/youtube/2026-01-30_clawdbot-personal-os-kitze.md similarity index 100% rename from notes/youtube/2026-01-30_clawdbot-personal-os-kitze.md rename to kb/youtube/2026-01-30_clawdbot-personal-os-kitze.md diff --git a/kb/youtube/2026-01-31_tony-robbins-secret-extraordinary-life.md b/kb/youtube/2026-01-31_tony-robbins-secret-extraordinary-life.md new file mode 100644 index 0000000..15c7111 --- /dev/null +++ b/kb/youtube/2026-01-31_tony-robbins-secret-extraordinary-life.md @@ -0,0 +1,123 @@ +# The Secret to an Extraordinary Life - Tony & Sage Robbins + +**Sursă:** https://youtu.be/FkcmW0Bbpao +**Cu:** Tony Robbins, Sage Robbins, Evaluna Montaner, Mau y Ricky +**Data notei:** 2026-01-31 +**Tags:** @growth, @development, @mindset + +--- + +## TL;DR + +Secretul unei vieți extraordinare nu e banii, poziția sau puterea - **e emoția**. Tony Robbins explică cum starea fizică, focusul și limbajul determină cum ne simțim. Pentru a te debloca: schimbă-ți corpul, schimbă-ți focusul, schimbă-ți cuvintele. + +--- + +## 🎯 Puncte Cheie + +### 1. Găsirea scopului în momente dificile + +> "Everything happens for a reason and a purpose greater than you know, but it's your job to find that reason." + +- Viața se întâmplă **pentru noi**, nu **cu noi** +- Hero's journey: viața pare OK → ceva se întâmplă → "call to adventure" (care pare moarte/sfârșit) +- **Nu ai un singur scop** - ai multiple scopuri în diferite contexte +- Caută scopul mai degrabă decât să încerci să "găsești" un scop unic + +### 2. Cum să te deblocezi (Pattern Interrupt) + +**Cele 3 lucruri care controlează cum te simți:** + +1. **Fiziologia** (corpul) + - Depresia are o postură: umeri căzuți, cap în jos, respirație superficială + - Energia/entuziasmul: energie sus, corp deschis + - **Schimbă corpul PRIMUL** - mișcă-te, respiră diferit + +2. **Focusul** (ce și cum) + - Nu doar CE vezi, ci CUM: imaginea e mare/mică? Aproape/departe? Color/alb-negru? + - Anxietatea: imagine mare, aproape, se îndepărtează (pierdere) + - Încrederea: imagine mare, se apropie de tine + +3. **Limbajul** + - Cuvintele atașate experienței DEVIN experiența + - "Nutritious snacks" vs "Delicious snacks" - percepție diferită + - Ce-ți spui când ești anxios vs când știi că vei reuși? + +**Tehnici rapide de deblocare:** +- Schimbare de temperatură (apă rece, saună) - resetează instant +- Mișcare (plimbare) - nu poți rămâne blocat când te miști +- "Can we begin again?" - reset în relații + +### 3. Priming (ritual zilnic Tony Robbins) + +Proces de 10 minute în fiecare dimineață: +- Intră într-o stare pozitivă +- Simte 3 lucruri pentru care ești recunoscător (nu doar le gândește, LE SIMTE) +- Recunoștința elimină frica și furia + +> "Work on gratitude and happiness is automatic." + +### 4. Relații și lucrul împreună + +- Businessul = misiune, nu doar muncă +- Fă momentele să conteze (hot tub catch-up, priviri, atingeri) +- Ritualuri de conectare (cina fără telefoane) +- "I love you too much to go this place" - oprește escaladarea +- Apreciază puzzle piece-ul fiecăruia - daruri diferite + +### 5. Începe de unde ești + +Povestea lui Tony: +- La 11 ani, familie săracă, Thanksgiving fără mâncare +- Un străin a adus mâncare → "Strangers care" +- La 17 ani: a hrănit 2 familii +- Apoi 4, 8, apoi 1 milion/an, 42 milioane în 37 ani +- Provocare: 100 miliarde mese în 10 ani (62 miliarde în 3 ani deja) + +> "If I won't give a dime out of a dollar, how will I ever give a million out of 10?" + +### 6. Cele 5 arii de stăpânit în viață + +1. **Corpul** - fără energie, nimic nu merge +2. **Emoțiile** - determină calitatea vieții +3. **Relațiile** - cea mai mare bucurie +4. **Timpul** - nu-l gestiona, CREEAZĂ viața +5. **Finanțele/Cariera + Spiritualitatea** - creștere și contribuție + +--- + +## 💡 Acțiuni Practice + +1. **Dimineața:** Priming 10 min - simte 3 lucruri pentru care ești recunoscător +2. **Când ești blocat:** Mișcă-te fizic, schimbă temperatura, mergi la plimbare +3. **În conflicte:** "Can we begin again?" sau "I love you too much for this" +4. **Pentru copii:** Respiră CU ei, nu doar le spune să respire +5. **Goals:** Stabilește obiective nerealiste cu timeline strâns (12-36 luni max) + +--- + +## 📝 Citate Memorabile + +> "What's wrong is always available. So is what's right." + +> "You don't experience life. You experience the life you focus on." + +> "My worst day became my best day." + +> "Scarcity is a lie." + +> "We're not made to manage life. We're made to create." + +> "Religion means to celebrate. You can't celebrate if you're not grateful." + +--- + +## 🔗 Resurse menționate + +- **Time to Rise Summit** - timetorisesummit.com (gratis, 3 zile x 3 ore) +- **Unleash the Power Within** - seminar live +- **Life Force** (carte Tony Robbins despre sănătate) + +--- + +*Video: ~1h conversation, familia Montaner cu Tony & Sage Robbins* diff --git a/notes/youtube/index.json b/kb/youtube/index.json similarity index 100% rename from notes/youtube/index.json rename to kb/youtube/index.json diff --git a/memory/2026-01-31.md b/memory/2026-01-31.md new file mode 100644 index 0000000..cc1c1a0 --- /dev/null +++ b/memory/2026-01-31.md @@ -0,0 +1,30 @@ +# Memory 2026-01-31 + +## Decizii + +### Dashboard statistici +- Adăugat secțiune statistici în index.html: task-uri azi/săptămâna/luna + insights +- Se calculează automat din tasks.json (coloana done) + +### Format insights cu tracking +- Checkboxes: `[ ]` neprocesat, `[x]` făcut, `[→]` backlog, `[—]` skip +- Prioritate: ⚡ urgent, 📌 important, 💡 nice-to-have +- Fiecare propunere cu link la sursă + +### Rapoarte actualizate (morning + evening) +- **Pas 0 NOU:** Scanare automată kb/youtube/ ultimele 48h + - Verifică dacă nota apare deja în insights + - Dacă nu → extrage și adaugă în insights/YYYY-MM-DD.md +- Verifică doar `[ ]` neprocesate din insights (AZI + IERI) + backlog +- După răspunsul lui Marius: marchează `[x]`/`[→]`/`[—]` + +### Backlog.md restructurat +- Secțiuni: Urgent+Important, Important, Nice-to-have, Făcut, Renunțat +- Același format checkbox ca insights + +## De făcut +- Verificare că rapoartele funcționează corect la 08:30 și 20:00 + +## Învățat +- Marius preferă totul într-un singur loc (scanare în raport, nu job separat) +- Insights trebuie să aibă status clar ca să nu se repete propunerile diff --git a/memory/heartbeat-state.json b/memory/heartbeat-state.json index 41847d6..6dfbfbf 100644 --- a/memory/heartbeat-state.json +++ b/memory/heartbeat-state.json @@ -1,6 +1,6 @@ { "lastChecks": { - "agents_sync": "2026-01-30", + "agents_sync": "2026-01-31", "email": null, "calendar": null, "git": 1738241820 diff --git a/notes/index.json b/notes/index.json deleted file mode 100644 index 10d5843..0000000 --- a/notes/index.json +++ /dev/null @@ -1,186 +0,0 @@ -{ - "notes": [ - { - "file": "youtube/2026-01-30_clawdbot-personal-os-kitze.md", - "title": "How I Use Clawdbot to Run My Business and Life 24/7", - "date": "2026-01-30", - "tags": [ - "clawdbot", - "productivity", - "personas", - "automation" - ], - "domains": [ - "work", - "growth" - ], - "video": "https://youtu.be/YRhGtHfs1Lw", - "tldr": "Kitze folosește **UN SINGUR gateway Clawdbot** cu **MULTIPLE PERSONAS** pe Telegram/Discord. Fiecare personă are:\n- Personalitate diferită (avatar, stil de vorbit)\n- Skills diferite (acces la tool-uri...", - "category": "youtube" - }, - { - "file": "retete/2026-01-30_ciorba-burta-falsa-cu-pui.md", - "title": "Ciorbă de Burtă Falsă cu Pui și Ciuperci Pleurotus", - "date": "2026-01-30", - "tags": [ - "ciorba", - "reteta", - "pleurotus", - "pui" - ], - "domains": [ - "health" - ], - "video": "", - "tldr": "", - "category": "retete" - }, - { - "file": "youtube/2026-01-29_remotion-skill-claude-code.md", - "title": "How people are generating videos with Claude Code (Remotion Skill)", - "date": "2026-01-29", - "tags": [ - "remotion", - "claude-code", - "video", - "automation" - ], - "domains": [ - "work" - ], - "video": "https://youtu.be/7OR-L0AySn8", - "tldr": "Remotion Skill permite generarea de videouri programatic cu Claude Code. Funcționează prin React components → video export. Demo live: Claude creează animații YouTube (like, subscribe, cursor) doar di...", - "category": "youtube" - }, - { - "file": "youtube/2026-01-29_gsd-framework-claude-code.md", - "title": "Forget Ralph Loops: The New GSD Framework for Claude Code", - "date": "2026-01-29", - "tags": [ - "claude-code", - "gsd", - "framework", - "sub-agents", - "automation" - ], - "domains": [ - "work" - ], - "video": "https://www.youtube.com/watch?v=l94A53kIUB0", - "tldr": "GSD (Get Shit Done) este un framework open-source pentru Claude Code care orchestrează sub-agenți pentru a completa proiecte urmând spec-driven development. Rezolvă problema \"context bloat\" prin rular...", - "category": "youtube" - }, - { - "file": "youtube/2026-01-29_greseli-post-apa.md", - "title": "Greșeli frecvente în timpul postului doar cu apă", - "date": "2026-01-29", - "tags": [ - "post", - "water-fasting", - "sănătate", - "detox" - ], - "domains": [ - "health" - ], - "video": "https://youtu.be/4QjkI0sf64M", - "tldr": "Greșelile frecvente pe care le fac oamenii când țin post terapeutic cu apă și cum să le eviți. Puncte cheie: pregătire corectă, curățarea colonului, calitatea apei, și importanța scopului spiritual.", - "category": "youtube" - }, - { - "file": "youtube/2026-01-29_cloudflare-tunnel-localhost-public.md", - "title": "Cloudflare Tunnel: Make Localhost Public Without Port Forwarding", - "date": "2026-01-29", - "tags": [ - "cloudflare", - "tunnel", - "localhost", - "networking", - "devops" - ], - "domains": [ - "work" - ], - "video": "https://youtu.be/etluT8UC-nw", - "tldr": "Cloudflare Tunnel permite expunerea unui server local (localhost) pe internet printr-un domeniu public, fără port forwarding, fără configurare router, fără expunerea IP-ului public. App-ul rămâne pe m...", - "category": "youtube" - }, - { - "file": "youtube/2026-01-29_clawdbot-security-vulnerabilities.md", - "title": "It Got Worse (Clawdbot) - Security Vulnerabilities", - "date": "2026-01-29", - "tags": [ - "clawdbot", - "security", - "vulnerabilities", - "hacking" - ], - "domains": [ - "work" - ], - "video": "https://youtu.be/rPAKq2oQVBs", - "tldr": "Video critic despre vulnerabilitățile de securitate ale Clawdbot - sute/mii de instanțe au fost compromise. Probleme principale: porturi default, parole lipsă, reverse proxy misconfigurat, skills mali...", - "category": "youtube" - }, - { - "file": "youtube/2025-01-30_clawdbot-5-use-cases.md", - "title": "5 Insane ClawdBot Use Cases You Need To Do Immediately", - "date": "2025-01-30", - "tags": [ - "clawdbot", - "automation", - "productivity", - "ai-assistant" - ], - "domains": [ - "work" - ], - "video": "https://www.youtube.com/watch?v=b-l9sGh1-UY", - "tldr": "5 use case-uri pentru ClawdBot care îl transformă dintr-un simplu chatbot într-un asistent proactiv care lucrează pentru tine chiar și când dormi.", - "category": "youtube" - }, - { - "file": "youtube/2025-01-30_claude-code-do-work-pattern.md", - "title": "The Most Powerful Claude Code Pattern I've Found", - "date": "2025-01-30", - "tags": [ - "claude-code", - "skills", - "workflow", - "automation", - "do-work" - ], - "domains": [ - "work" - ], - "video": "https://youtu.be/I9-tdhxiH7w", - "tldr": "Un pattern puternic pentru Claude Code: **Do Work** - o coadă de task-uri pe care Claude le procesează automat, unul câte unul, în sub-agenți cu context curat. Ideea cheie: **construiește tool-uri pen...", - "category": "youtube" - } - ], - "stats": { - "total": 9, - "by_domain": { - "work": 7, - "health": 2, - "growth": 1, - "sprijin": 0, - "scout": 0 - }, - "by_category": { - "youtube": 8, - "retete": 1 - } - }, - "domains": [ - "work", - "health", - "growth", - "sprijin", - "scout" - ], - "categories": [ - "youtube", - "retete" - ] -} \ No newline at end of file diff --git a/anaf-monitor/bilant_compare/2025_vs_2024/RAPORT_2025_vs_2024.md b/tools/anaf-monitor/bilant_compare/2025_vs_2024/RAPORT_2025_vs_2024.md similarity index 100% rename from anaf-monitor/bilant_compare/2025_vs_2024/RAPORT_2025_vs_2024.md rename to tools/anaf-monitor/bilant_compare/2025_vs_2024/RAPORT_2025_vs_2024.md diff --git a/anaf-monitor/bilant_compare/2025_vs_2024/s1002_2024.xsd b/tools/anaf-monitor/bilant_compare/2025_vs_2024/s1002_2024.xsd similarity index 100% rename from anaf-monitor/bilant_compare/2025_vs_2024/s1002_2024.xsd rename to tools/anaf-monitor/bilant_compare/2025_vs_2024/s1002_2024.xsd diff --git a/anaf-monitor/bilant_compare/2025_vs_2024/s1002_2025.xsd b/tools/anaf-monitor/bilant_compare/2025_vs_2024/s1002_2025.xsd similarity index 100% rename from anaf-monitor/bilant_compare/2025_vs_2024/s1002_2025.xsd rename to tools/anaf-monitor/bilant_compare/2025_vs_2024/s1002_2025.xsd diff --git a/anaf-monitor/bilant_compare/RAPORT_DIFERENTE_2024_vs_2023.md b/tools/anaf-monitor/bilant_compare/RAPORT_DIFERENTE_2024_vs_2023.md similarity index 100% rename from anaf-monitor/bilant_compare/RAPORT_DIFERENTE_2024_vs_2023.md rename to tools/anaf-monitor/bilant_compare/RAPORT_DIFERENTE_2024_vs_2023.md diff --git a/anaf-monitor/bilant_compare/s1002_2023.xsd b/tools/anaf-monitor/bilant_compare/s1002_2023.xsd similarity index 100% rename from anaf-monitor/bilant_compare/s1002_2023.xsd rename to tools/anaf-monitor/bilant_compare/s1002_2023.xsd diff --git a/anaf-monitor/bilant_compare/s1002_2024.xsd b/tools/anaf-monitor/bilant_compare/s1002_2024.xsd similarity index 100% rename from anaf-monitor/bilant_compare/s1002_2024.xsd rename to tools/anaf-monitor/bilant_compare/s1002_2024.xsd diff --git a/anaf-monitor/bilant_compare/s1003_2023.xsd b/tools/anaf-monitor/bilant_compare/s1003_2023.xsd similarity index 100% rename from anaf-monitor/bilant_compare/s1003_2023.xsd rename to tools/anaf-monitor/bilant_compare/s1003_2023.xsd diff --git a/anaf-monitor/bilant_compare/s1003_2024.xsd b/tools/anaf-monitor/bilant_compare/s1003_2024.xsd similarity index 100% rename from anaf-monitor/bilant_compare/s1003_2024.xsd rename to tools/anaf-monitor/bilant_compare/s1003_2024.xsd diff --git a/anaf-monitor/bilant_compare/s1004_2023.xsd b/tools/anaf-monitor/bilant_compare/s1004_2023.xsd similarity index 100% rename from anaf-monitor/bilant_compare/s1004_2023.xsd rename to tools/anaf-monitor/bilant_compare/s1004_2023.xsd diff --git a/anaf-monitor/bilant_compare/s1004_2024.xsd b/tools/anaf-monitor/bilant_compare/s1004_2024.xsd similarity index 100% rename from anaf-monitor/bilant_compare/s1004_2024.xsd rename to tools/anaf-monitor/bilant_compare/s1004_2024.xsd diff --git a/anaf-monitor/bilant_compare/s1005_2023.xsd b/tools/anaf-monitor/bilant_compare/s1005_2023.xsd similarity index 100% rename from anaf-monitor/bilant_compare/s1005_2023.xsd rename to tools/anaf-monitor/bilant_compare/s1005_2023.xsd diff --git a/anaf-monitor/bilant_compare/s1005_2024.xsd b/tools/anaf-monitor/bilant_compare/s1005_2024.xsd similarity index 100% rename from anaf-monitor/bilant_compare/s1005_2024.xsd rename to tools/anaf-monitor/bilant_compare/s1005_2024.xsd diff --git a/anaf-monitor/bilant_compare/structura_2023.pdf b/tools/anaf-monitor/bilant_compare/structura_2023.pdf similarity index 100% rename from anaf-monitor/bilant_compare/structura_2023.pdf rename to tools/anaf-monitor/bilant_compare/structura_2023.pdf diff --git a/anaf-monitor/bilant_compare/structura_2024.pdf b/tools/anaf-monitor/bilant_compare/structura_2024.pdf similarity index 100% rename from anaf-monitor/bilant_compare/structura_2024.pdf rename to tools/anaf-monitor/bilant_compare/structura_2024.pdf diff --git a/anaf-monitor/config.json b/tools/anaf-monitor/config.json similarity index 100% rename from anaf-monitor/config.json rename to tools/anaf-monitor/config.json diff --git a/anaf-monitor/hashes.json b/tools/anaf-monitor/hashes.json similarity index 100% rename from anaf-monitor/hashes.json rename to tools/anaf-monitor/hashes.json diff --git a/anaf-monitor/monitor.py b/tools/anaf-monitor/monitor.py similarity index 100% rename from anaf-monitor/monitor.py rename to tools/anaf-monitor/monitor.py diff --git a/anaf-monitor/monitor.sh b/tools/anaf-monitor/monitor.sh similarity index 100% rename from anaf-monitor/monitor.sh rename to tools/anaf-monitor/monitor.sh diff --git a/anaf-monitor/monitor_v2.py b/tools/anaf-monitor/monitor_v2.py similarity index 100% rename from anaf-monitor/monitor_v2.py rename to tools/anaf-monitor/monitor_v2.py diff --git a/anaf-monitor/versions.json b/tools/anaf-monitor/versions.json similarity index 100% rename from anaf-monitor/versions.json rename to tools/anaf-monitor/versions.json diff --git a/tools/update_notes_index.py b/tools/update_notes_index.py index 044e371..0ad1578 100644 --- a/tools/update_notes_index.py +++ b/tools/update_notes_index.py @@ -1,25 +1,75 @@ #!/usr/bin/env python3 """ -Generează index.json pentru notes din fișierele .md +Generează index.json pentru KB din fișierele .md +Scanează: kb/, memory/, conversations/ Extrage titlu, dată, tags, și domenii (@work, @health, etc.) -Scanează TOATE subdirectoarele din notes/ (youtube, retete, etc.) """ import os import re import json from pathlib import Path +from datetime import datetime -NOTES_ROOT = Path(__file__).parent.parent / "notes" -INDEX_FILE = NOTES_ROOT / "index.json" - -# Subdirectoare de scanat (adaugă altele aici) -SCAN_DIRS = ['youtube', 'retete'] +BASE_DIR = Path(__file__).parent.parent +KB_ROOT = BASE_DIR / "kb" +MEMORY_DIR = BASE_DIR / "memory" +CONVERSATIONS_DIR = BASE_DIR / "conversations" +INDEX_FILE = KB_ROOT / "index.json" # Domenii de agenți VALID_DOMAINS = ['work', 'health', 'growth', 'sprijin', 'scout'] -def extract_metadata(filepath): +# Tipuri speciale (pentru grup-sprijin etc.) +VALID_TYPES = ['exercitiu', 'meditatie', 'reflectie', 'intrebare', 'fisa', 'project', 'memory', 'conversation', 'coaching'] + +# Cache for rules files +_rules_cache = {} + +def load_rules(filepath): + """Încarcă regulile din .rules.json din directorul fișierului sau părinți""" + dir_path = filepath.parent + + # Check cache + if str(dir_path) in _rules_cache: + return _rules_cache[str(dir_path)] + + # Look for .rules.json in current dir and parents (up to kb/) + rules = { + "defaultDomains": [], + "defaultTypes": [], + "defaultTags": [], + "inferTypeFromFilename": False, + "filenameTypeMap": {} + } + + # Collect rules from all levels (child rules override parent) + rules_chain = [] + current = dir_path + while current >= KB_ROOT: + rules_file = current / ".rules.json" + if rules_file.exists(): + try: + with open(rules_file, 'r', encoding='utf-8') as f: + rules_chain.insert(0, json.load(f)) # Parent first + except: + pass + current = current.parent + + # Merge rules (child overrides parent) + for r in rules_chain: + for key in rules: + if key in r: + if isinstance(rules[key], list): + # Extend lists (don't override) + rules[key] = list(set(rules[key] + r[key])) + else: + rules[key] = r[key] + + _rules_cache[str(dir_path)] = rules + return rules + +def extract_metadata(filepath, category, subcategory=None): """Extrage metadata din fișierul markdown""" with open(filepath, 'r', encoding='utf-8') as f: content = f.read() @@ -31,6 +81,7 @@ def extract_metadata(filepath): # Extrage tags (linia cu **Tags:** sau tags:) tags = [] domains = [] + types = [] tags_match = re.search(r'\*\*Tags?:\*\*\s*(.+)$|^Tags?:\s*(.+)$', content, re.MULTILINE | re.IGNORECASE) if tags_match: tags_str = tags_match.group(1) or tags_match.group(2) @@ -38,96 +89,199 @@ def extract_metadata(filepath): # Extrage domenii (@work, @health, etc.) domain_matches = re.findall(r'@(\w+)', tags_str) domains = [d for d in domain_matches if d in VALID_DOMAINS] + types = [d for d in domain_matches if d in VALID_TYPES] - # Extrage tags normale (#tag) - exclude domeniile + # Extrage tags normale (#tag) all_tags = re.findall(r'#([\w-]+)', tags_str) - tags = [t for t in all_tags if t not in VALID_DOMAINS] + tags = [t for t in all_tags if t not in VALID_DOMAINS and t not in VALID_TYPES] - # Extrage data din filename (YYYY-MM-DD_slug.md) - date_match = re.match(r'(\d{4}-\d{2}-\d{2})_', filepath.name) + # Aplică reguli din .rules.json (dacă există) + rules = load_rules(filepath) + + # Adaugă domains implicite (dacă nu sunt deja) + for d in rules.get("defaultDomains", []): + if d not in domains: + domains.append(d) + + # Adaugă types implicite + for t in rules.get("defaultTypes", []): + if t not in types: + types.append(t) + + # Adaugă tags implicite + for t in rules.get("defaultTags", []): + if t not in tags: + tags.append(t) + + # Inferă type din filename (dacă e configurat) + if rules.get("inferTypeFromFilename"): + filename_lower = filepath.stem.lower() + for pattern, type_name in rules.get("filenameTypeMap", {}).items(): + if pattern in filename_lower and type_name not in types: + types.append(type_name) + break + + # Extrage data din filename (YYYY-MM-DD_slug.md sau YYYY-MM-DD.md) + date_match = re.match(r'(\d{4}-\d{2}-\d{2})', filepath.name) date = date_match.group(1) if date_match else "" + # Pentru fișiere fără dată în nume, folosește mtime + if not date: + mtime = filepath.stat().st_mtime + date = datetime.fromtimestamp(mtime).strftime('%Y-%m-%d') + # Extrage video URL video_match = re.search(r'\*\*(?:Video|Link):\*\*\s*(https?://[^\s]+)', content) video_url = video_match.group(1) if video_match else "" - # Extrage TL;DR (primele 200 caractere) - tldr_match = re.search(r'##\s*📋?\s*TL;DR\s*\n+(.+?)(?=\n##|\n---|\Z)', content, re.DOTALL) + # Extrage TL;DR sau primele 200 caractere de conținut tldr = "" + tldr_match = re.search(r'##\s*📋?\s*TL;DR\s*\n+(.+?)(?=\n##|\n---|\Z)', content, re.DOTALL) if tldr_match: tldr = tldr_match.group(1).strip()[:200] - if len(tldr_match.group(1).strip()) > 200: - tldr += "..." + else: + # Fallback: primul paragraf după titlu + para_match = re.search(r'^#.+\n+(.+?)(?=\n\n|\n#|\Z)', content, re.DOTALL) + if para_match: + tldr = para_match.group(1).strip()[:200] + if len(tldr) >= 200: + tldr += "..." + + # Construiește path-ul relativ pentru web (din dashboard/) + # Dashboard are symlinks: notes-data -> ../kb, memory -> ../memory, conversations -> ../conversations + rel_path = str(filepath.relative_to(BASE_DIR)) + # Transformă kb/... în notes-data/... pentru web + if rel_path.startswith('kb/'): + rel_path = 'notes-data/' + rel_path[3:] return { - "file": filepath.name, + "file": rel_path, "title": title, "date": date, "tags": tags, "domains": domains, + "types": types, + "category": category, + "project": subcategory, # primul nivel sub projects/ (grup-sprijin, vending-master) + "subdir": None, # se setează în scan_directory pentru niveluri mai adânci "video": video_url, "tldr": tldr } -def generate_index(): - """Generează index.json din toate fișierele .md din toate subdirectoarele""" +def scan_directory(dir_path, category, subcategory=None, recursive=False): + """Scanează un director pentru fișiere .md""" notes = [] - # Stats per domeniu - domain_stats = {d: 0 for d in VALID_DOMAINS} - # Stats per categorie - category_stats = {} + if not dir_path.exists(): + return notes - for subdir in SCAN_DIRS: - notes_dir = NOTES_ROOT / subdir - if not notes_dir.exists(): - print(f" (skipping {subdir}/ - not found)") - continue - - print(f"Scanning notes/{subdir}/...") - category_stats[subdir] = 0 - - for filepath in sorted(notes_dir.glob("*.md"), reverse=True): - if filepath.name == 'index.json': + # Defaults pentru categorii speciale (memory/, conversations/) + category_defaults = { + "memory": {"types": ["memory"], "domains": []}, + "conversations": {"types": ["conversation"], "domains": []} + } + + if recursive: + # Scanează recursiv + for filepath in dir_path.rglob("*.md"): + if filepath.name.startswith('.') or 'template' in filepath.name.lower(): continue try: - metadata = extract_metadata(filepath) - # Adaugă categoria (subdirectorul) - metadata['category'] = subdir - # Modifică path-ul fișierului să includă subdirectorul - metadata['file'] = f"{subdir}/{filepath.name}" + # Determină project și subdir din path + # Ex: projects/grup-sprijin/biblioteca/file.md + # project = grup-sprijin, subdir = biblioteca + rel_to_dir = filepath.relative_to(dir_path) + parts = rel_to_dir.parts[:-1] # exclude filename + + project = parts[0] if len(parts) > 0 else None + subdir = parts[1] if len(parts) > 1 else None + + metadata = extract_metadata(filepath, category, project) + metadata['subdir'] = subdir notes.append(metadata) - - # Update stats - category_stats[subdir] += 1 - for d in metadata['domains']: - domain_stats[d] += 1 - - domains_str = ' '.join([f'@{d}' for d in metadata['domains']]) if metadata['domains'] else '' - print(f" + {metadata['title'][:40]}... {domains_str}") except Exception as e: - print(f" ! Error processing {filepath.name}: {e}") + print(f" ! Error processing {filepath}: {e}") + else: + # Scanează doar fișierele din director (nu subdirectoare) + for filepath in sorted(dir_path.glob("*.md"), reverse=True): + if filepath.name.startswith('.') or 'template' in filepath.name.lower(): + continue + try: + metadata = extract_metadata(filepath, category, subcategory) + # Aplică defaults pentru categoria specială + if category in category_defaults: + defaults = category_defaults[category] + for t in defaults.get("types", []): + if t not in metadata["types"]: + metadata["types"].append(t) + for d in defaults.get("domains", []): + if d not in metadata["domains"]: + metadata["domains"].append(d) + notes.append(metadata) + except Exception as e: + print(f" ! Error processing {filepath}: {e}") + + return notes + +def generate_index(): + """Generează index.json din toate sursele""" + all_notes = [] + + # Stats + domain_stats = {d: 0 for d in VALID_DOMAINS} + category_stats = {} + + # Scanează TOATE subdirectoarele din kb/ recursiv + print("Scanning kb/ (all subdirectories)...") + for subdir in sorted(KB_ROOT.iterdir()): + if subdir.is_dir() and not subdir.name.startswith('.'): + category = subdir.name + print(f" [{category}]") + notes = scan_directory(subdir, category, recursive=True) + all_notes.extend(notes) + category_stats[category] = len(notes) + for n in notes: + sub = f"/{n['subcategory']}" if n.get('subcategory') else "" + print(f" + {n['title'][:42]}...") + for d in n['domains']: + domain_stats[d] += 1 + + # 4. Scanează memory/ + print("Scanning memory/...") + memory_notes = scan_directory(MEMORY_DIR, "memory") + all_notes.extend(memory_notes) + category_stats["memory"] = len(memory_notes) + for n in memory_notes: + print(f" + {n['title'][:45]}...") + + # 5. Scanează conversations/ + print("Scanning conversations/...") + conv_notes = scan_directory(CONVERSATIONS_DIR, "conversations") + all_notes.extend(conv_notes) + category_stats["conversations"] = len(conv_notes) + for n in conv_notes: + print(f" + {n['title'][:45]}...") # Sortează după dată descrescător - notes.sort(key=lambda x: x['date'], reverse=True) + all_notes.sort(key=lambda x: x['date'], reverse=True) # Adaugă metadata globală output = { - "notes": notes, + "notes": all_notes, "stats": { - "total": len(notes), + "total": len(all_notes), "by_domain": domain_stats, "by_category": category_stats }, "domains": VALID_DOMAINS, - "categories": SCAN_DIRS + "types": VALID_TYPES, + "categories": list(category_stats.keys()) } with open(INDEX_FILE, 'w', encoding='utf-8') as f: json.dump(output, f, indent=2, ensure_ascii=False) - print(f"\n✅ Generated {INDEX_FILE} with {len(notes)} notes") - print(f" Domains: {domain_stats}") + print(f"\n✅ Generated {INDEX_FILE} with {len(all_notes)} notes") print(f" Categories: {category_stats}") return output