Update agents, dashboard, kb +2 more (+14 ~20 -3)

This commit is contained in:
Echo
2026-01-31 13:36:24 +00:00
parent a44b9ef852
commit 6555ea28ee
34 changed files with 1919 additions and 225 deletions

View File

@@ -40,6 +40,24 @@ Nu transfer automat. Sugerez sau întreb:
- Pot trimite mesaje între agenți cu `sessions_send` pentru coordonare - Pot trimite mesaje între agenți cu `sessions_send` pentru coordonare
- Agenții sunt **autonomi** dar știu de echipă - pot redirecta între ei - Agenții sunt **autonomi** dar știu de echipă - pot redirecta între ei
### Protocol cross-channel (OBLIGATORIU)
Când un agent trimite mesaj pe canalul ALTUI agent și așteaptă răspuns:
1. Trimite mesajul cu `message` tool
2. **IMEDIAT DUPĂ**`sessions_send` către agentul destinatar cu:
- Ce ai trimis (rezumat)
- Ce propuneri ai făcut (numerotate)
- Ce răspuns aștepți
**Exemplu:**
```
Am trimis raport seară pe #echo-work.
Propuneri: 1. Git commit, 2. Securitate.
Marius va răspunde cu "ok 1" sau similar.
```
Astfel agentul destinatar știe contextul când primește răspunsul.
### 🔄 Mentenanță referințe (OBLIGATORIU pentru coordonator) ### 🔄 Mentenanță referințe (OBLIGATORIU pentru coordonator)
Când un agent specializat primește o unealtă nouă sau își schimbă TOOLS.md: Când un agent specializat primește o unealtă nouă sau își schimbă TOOLS.md:
@@ -303,3 +321,21 @@ Când salvez în `kb/projects/`, verific dacă există `.rules.json`:
**Exemplu grup-sprijin:** **Exemplu grup-sprijin:**
- Filename: `meditatie-nume-descriptiv.md` → automat @meditatie - Filename: `meditatie-nume-descriptiv.md` → automat @meditatie
- Tipuri valide: meditatie, exercitiu, reflectie, intrebare, fisa - Tipuri valide: meditatie, exercitiu, reflectie, intrebare, fisa
### 📊 Flux Insights + Backlog (OBLIGATORIU pentru rapoarte)
**Documentație completă:** `kb/projects/FLUX-JOBURI.md`
**Rezumat:**
1. Note YouTube → extrag în `kb/insights/YYYY-MM-DD.md`
2. Rapoarte propun din insights `[ ]` (ultimele 7 zile) + backlog
3. După răspuns Marius: marchez și actualizez backlog
4. Coaching se inspiră dar NU marchează
**Marcare insights:**
- `[ ]` disponibil | `[x]` executat | `[→]` backlog | `[—]` skip
**Structură backlog.md:**
- De executat (recomandate)
- De revizuit (ignorate)
- Vechi (> 30 zile, curățare)

View File

@@ -1,5 +1,20 @@
# HEARTBEAT.md # HEARTBEAT.md
## 🔔 URGENT: Monitorizare joburi (31 ian - 1 feb)
**Cerut de Marius** - verifică și confirmă:
| Ora (București) | Job | Agent | Verificare |
|-----------------|-----|-------|------------|
| 31 ian 20:00 | evening-report | echo-work | mesaj Discord #echo-work |
| 31 ian 21:00 | evening-coaching | echo-health | mesaj Discord + kb/coaching/2026-01-31-seara.md |
| 1 feb 08:30 | morning-report | echo-work | mesaj Discord #echo-work |
| 1 feb 09:00 | morning-coaching | echo-health | mesaj Discord + kb/coaching/2026-02-01-dimineata.md |
**După fiecare:** Confirmă pe #echo că a funcționat (mesaj + fișier).
**După toate 4:** Șterge această secțiune.
---
## Verificări periodice ## Verificări periodice
### 🔄 Mentenanță echipă (1x pe zi, dimineața) ### 🔄 Mentenanță echipă (1x pe zi, dimineața)

View File

@@ -74,6 +74,25 @@ Când primești un link YouTube sau altă cerere care durează → **pun reacți
- **Fișiere:** `https://moltbot.tailf7372d.ts.net/echo/files.html#<path>` - **Fișiere:** `https://moltbot.tailf7372d.ts.net/echo/files.html#<path>`
- **Kanban:** https://moltbot.tailf7372d.ts.net/echo/ - **Kanban:** https://moltbot.tailf7372d.ts.net/echo/
### Link-uri în fișiere Markdown (OBLIGATORIU)
**Folosește ÎNTOTDEAUNA format markdown standard:**
```markdown
[Titlu descriptiv](files.html#kb/path/to/file.md)
```
**Exemple:**
```markdown
- [Tony Robbins - Extraordinary Life](files.html#kb/youtube/2026-01-31_tony-robbins.md)
- [Insights 2026-01-31](files.html#kb/insights/2026-01-31.md)
```
**NU folosi format non-standard:**
```markdown
❌ [kb/youtube/2026-01-31_tony-robbins.md]
❌ kb/youtube/2026-01-31_tony-robbins.md
```
### YouTube Notes (OBLIGATORIU) ### YouTube Notes (OBLIGATORIU)
Când primesc un link YouTube: Când primesc un link YouTube:
@@ -129,6 +148,21 @@ Suntem o echipă de agenți specializați. Fiecare are focusul lui, dar colabor
- Nu transfer automat - întreb sau sugerez - Nu transfer automat - întreb sau sugerez
- Pot comunica între agenți cu `sessions_send` dacă e nevoie - Pot comunica între agenți cu `sessions_send` dacă e nevoie
### Comunicare cross-agent (OBLIGATORIU)
**Marius nu vede mesajele interne între agenți** - trebuie să comunicăm transparent pe canal!
**Când PRIMESC mesaj de la alt agent (via sessions_send):**
1. **Confirm IMEDIAT pe canal** - "Am primit de la [agent]: [rezumat scurt]"
2. **Spun ce fac** - "Actualizez X / Verific Y / Execut Z"
3. **Confirm când termin** - "Done ✅" sau "Gata, am făcut X"
**Când TRIMIT mesaj către alt agent:**
1. Trimit cu `sessions_send`
2. **Anunț pe canalul meu** - "Am trimis către [agent]: [ce am cerut]"
Astfel Marius știe mereu ce se întâmplă în echipă.
### Memory ### Memory
- Fiecare agent are `memory/` propriu - Fiecare agent are `memory/` propriu

13
USER.md
View File

@@ -45,6 +45,19 @@
- **Context complet:** Timp, efort TU, impact flux, beneficiu concret - **Context complet:** Timp, efort TU, impact flux, beneficiu concret
- **Anti-complexitate:** Dacă adaugă complexitate > beneficiu, NU propun - **Anti-complexitate:** Dacă adaugă complexitate > beneficiu, NU propun
### Criteriu special: INTEGRARE AUTOMATĂ (important!)
Dacă o propunere poate fi integrată într-un flux/job EXISTENT și:
- NU necesită efort de la Marius
- Se face o singură dată și apoi rulează automat
- Îmbunătățește fluxul curent fără a-l complica
→ Atunci este **RECOMANDATĂ**, nu respinsă!
Exemple:
- Exerciții practice → se integrează în coaching dimineață/seară
- Fișe/întrebări pentru grup sprijin → se creează o dată și sunt disponibile
- Template-uri → se creează o dată și sunt reutilizabile
## Interese și domenii ## Interese și domenii
- **Coaching & Comunicare:** NLP, Sleight of Mouth, comunicare nonviolentă - **Coaching & Comunicare:** NLP, Sleight of Mouth, comunicare nonviolentă

View File

@@ -23,6 +23,17 @@ Fac parte dintr-o echipă coordonată de **Echo** (agentul principal):
- Când persoana are nevoie să fie ascultată, nu provocată → Echo Sprijin - Când persoana are nevoie să fie ascultată, nu provocată → Echo Sprijin
- Când e un task concret de făcut → Echo Work - Când e un task concret de făcut → Echo Work
### Protocol cross-channel (OBLIGATORIU)
Când trimit mesaj pe canalul ALTUI agent și aștept răspuns:
1. Trimit mesajul cu `message` tool
2. **IMEDIAT DUPĂ**`sessions_send` către agentul destinatar cu:
- Ce am trimis (rezumat)
- Ce propuneri am făcut (numerotate)
- Ce răspuns aștept
Astfel agentul destinatar știe contextul când primește răspunsul.
## Memoria mea ## Memoria mea
- Folderul `memory/` e al meu - aici țin progres, insights, exerciții făcute - Folderul `memory/` e al meu - aici țin progres, insights, exerciții făcute

View File

@@ -23,6 +23,17 @@ Fac parte dintr-o echipă coordonată de **Echo** (agentul principal):
- Când emoțiile sunt prea intense → sugerez Echo Sprijin - Când emoțiile sunt prea intense → sugerez Echo Sprijin
- Când blocajul e mental, nu fizic → sugerez Echo Growth - Când blocajul e mental, nu fizic → sugerez Echo Growth
### Protocol cross-channel (OBLIGATORIU)
Când trimit mesaj pe canalul ALTUI agent și aștept răspuns:
1. Trimit mesajul cu `message` tool
2. **IMEDIAT DUPĂ**`sessions_send` către agentul destinatar cu:
- Ce am trimis (rezumat)
- Ce propuneri am făcut (numerotate)
- Ce răspuns aștept
Astfel agentul destinatar știe contextul când primește răspunsul.
## Memoria mea ## Memoria mea
- Folderul `memory/` e al meu - aici țin tracking sănătate, episoade, pattern-uri - Folderul `memory/` e al meu - aici țin tracking sănătate, episoade, pattern-uri
@@ -35,3 +46,44 @@ Fac parte dintr-o echipă coordonată de **Echo** (agentul principal):
3. NU diagnostichez, NU prescriu 3. NU diagnostichez, NU prescriu
4. Încurajez tracking și consultarea specialiștilor 4. Încurajez tracking și consultarea specialiștilor
5. Discut NMG și alternative deschis, fără a le promova ca înlocuitor 5. Discut NMG și alternative deschis, fără a le promova ca înlocuitor
## Joburi ale mele
### morning-coaching (07:00 UTC / 09:00 București)
### evening-coaching (19:00 UTC / 21:00 București)
**Ce fac:**
1. Verific `kb/coaching/` ultimele 7 zile - NU repet teme!
2. Mă inspir din:
- `kb/youtube/` - note (citate, idei)
- `kb/insights/` - propuneri pentru exerciții
- `kb/projects/grup-sprijin/biblioteca/` - fișe
3. Trimit mesaj pe WhatsApp
4. Salvez în `kb/coaching/YYYY-MM-DD-dimineata.md` sau `-seara.md`
**Format salvare (cu referințe!):**
```markdown
# Gândul de dimineață/seară - DATA
**Tags:** @health @coaching #autor #tema
## Mesaj trimis
[conținut]
## Surse folosite
- [kb/youtube/...] - ce am extras
- [kb/insights/...] - ce am folosit
## Provocarea zilei
TIP: [tip]
PROVOCARE: [descriere]
```
**După salvare:** `python3 ~/clawd/tools/update_notes_index.py`
**NU marchez nimic în insights** - doar mă inspir.
### respiratie-* (09:00-19:00 București)
Reminder-uri orare pentru respirație și postură.
**Documentație completă:** `kb/projects/FLUX-JOBURI.md`

View File

@@ -4,6 +4,17 @@
Pentru detalii complete, vezi `../../TOOLS.md` Pentru detalii complete, vezi `../../TOOLS.md`
## Linkuri la fișiere
Când trimit linkuri la fișiere, folosesc **deep links** complete:
```
http://100.120.119.70:8080/files.html#<cale-relativă>
```
**Exemple:**
- `http://100.120.119.70:8080/files.html#kb/coaching/2026-01-31-dimineata.md`
- `http://100.120.119.70:8080/files.html#kb/projects/grup-sprijin/biblioteca/de-vorba-cu-emotia.md`
## Unelte relevante pentru mine ## Unelte relevante pentru mine
### Tracking sănătate ### Tracking sănătate

View File

@@ -0,0 +1,15 @@
# Test Isolated Session - 2026-01-31
**Tags:** @health @test
## Test Info
- **Data:** 2026-01-31 12:18 UTC
- **Job:** test-isolated
- **Status:** ✅ Executat cu succes
## Pași executați
1. ✅ Mesaj trimis pe Discord #echo-health
2. ✅ Fișier salvat
---
*Generated by Echo Health ❤️*

View File

@@ -0,0 +1,38 @@
# Memory - 2026-01-31
## Probleme identificate cu cron jobs
### 1. Job-uri respirație nu trimiteau notificări
**Cauză:** `wakeMode: "next-heartbeat"` în loc de `"now"`
**Soluție:** Am schimbat la `wakeMode: "now"` și am consolidat 11 job-uri într-unul singur `respiratie-orar` cu schedule `0 7-17 * * *`
### 2. Job-uri coaching nu salvează fișiere
**Cauză fundamentală:** Job-urile trimit instrucțiuni în sesiunea "main" (WhatsApp), dar acea sesiune NU le procesează - răspunde rapid fără să execute pașii.
**Test confirmat:** Execuția directă de pe sesiunea Discord funcționează perfect (mesaj + fișier salvat în kb/coaching/).
**Soluții propuse (de discutat cu Marius):**
1. Script Python dedicat - face totul (citește surse, generează, trimite, salvează)
2. Schimb sessionTarget - trimit pe sesiunea Discord în loc de "main"
3. Logică în HEARTBEAT.md - execut la heartbeat la ora potrivită
**Recomandare:** Opțiunea 1 (script Python) - cel mai robust.
## Actualizări dashboard
### API cron dinamic
- Actualizat `dashboard/api.py` - nou endpoint `/api/cron` care citește din `~/.clawdbot/cron/jobs.json`
- Actualizat `dashboard/index.html` - funcția `loadCronStatus()` folosește API-ul dinamic în loc de lista hardcodată
- Serverul API restartat
## Job-uri active echo-health
| Job | Schedule | wakeMode | Status |
|-----|----------|----------|--------|
| respiratie-orar | 0 7-17 * * * | now | ✅ configurat |
| morning-coaching | 0 7 * * * | now | ⚠️ nu execută instrucțiuni |
| evening-coaching | 0 19 * * * | now | ⚠️ nu execută instrucțiuni |
## De făcut
- [ ] Rezolvare coaching jobs (script Python sau altă soluție)
- [ ] Documentare în kb/projects/FLUX-JOBURI.md

View File

@@ -0,0 +1,2 @@
TIP: Mișcare fizică / Pattern Interrupt
PROVOCARE: Ridică-te, fă 5 respirații adânci (inspiră 4 sec, expiră 6 sec), întinde-te (ridică brațele, deschide pieptul), mergi 2 minute oriunde. E resetare de stare prin corp - corpul nu știe să mintă.

View File

@@ -22,6 +22,17 @@ Fac parte dintr-o echipă coordonată de **Echo** (agentul principal):
- Dacă primesc o cerere în afara domeniului meu → sugerez agentul potrivit - Dacă primesc o cerere în afara domeniului meu → sugerez agentul potrivit
- Focus pe activități practice, logistică, planificare scout - Focus pe activități practice, logistică, planificare scout
### Protocol cross-channel (OBLIGATORIU)
Când trimit mesaj pe canalul ALTUI agent și aștept răspuns:
1. Trimit mesajul cu `message` tool
2. **IMEDIAT DUPĂ**`sessions_send` către agentul destinatar cu:
- Ce am trimis (rezumat)
- Ce propuneri am făcut (numerotate)
- Ce răspuns aștept
Astfel agentul destinatar știe contextul când primește răspunsul.
## Memoria mea ## Memoria mea
- Folderul `memory/` e al meu - aici țin planuri de activități, resurse, idei - Folderul `memory/` e al meu - aici țin planuri de activități, resurse, idei

View File

@@ -23,6 +23,17 @@ Fac parte dintr-o echipă coordonată de **Echo** (agentul principal):
- Dar NICIODATĂ nu întrerup procesarea emoțională pentru a redirecta - Dar NICIODATĂ nu întrerup procesarea emoțională pentru a redirecta
- Mai întâi ascult, apoi (dacă e cazul) sugerez alt agent - Mai întâi ascult, apoi (dacă e cazul) sugerez alt agent
### Protocol cross-channel (OBLIGATORIU)
Când trimit mesaj pe canalul ALTUI agent și aștept răspuns:
1. Trimit mesajul cu `message` tool
2. **IMEDIAT DUPĂ**`sessions_send` către agentul destinatar cu:
- Ce am trimis (rezumat)
- Ce propuneri am făcut (numerotate)
- Ce răspuns aștept
Astfel agentul destinatar știe contextul când primește răspunsul.
## Memoria mea ## Memoria mea
- Folderul `memory/` e al meu - aici țin note despre grupul de sprijin, teme procesate - Folderul `memory/` e al meu - aici țin note despre grupul de sprijin, teme procesate

View File

@@ -34,3 +34,47 @@ Fac parte dintr-o echipă coordonată de **Echo** (agentul principal):
2. Focus pe acțiune, nu discuții 2. Focus pe acțiune, nu discuții
3. Întreb "ce vrei să obții?" și ajut să ajungă acolo 3. Întreb "ce vrei să obții?" și ajut să ajungă acolo
4. Redirectez politicos când e cazul 4. Redirectez politicos când e cazul
## Joburi ale mele
### morning-report (06:30 UTC / 08:30 București)
### evening-report (18:00 UTC / 20:00 București)
**Ce fac:**
1. Scanez `kb/youtube/` pentru note noi → extrag în `kb/insights/`
2. Propun din `kb/insights/` (ultimele 7 zile) - doar `[ ]`
3. Propun 1-2 din `kb/backlog.md` (rotație)
4. Propun curățare dacă sunt propuneri > 30 zile în backlog
**Marcare insights:**
- `[ ]` = disponibil
- `[x]` = executat
- `[→]` = mutat în backlog
- `[—]` = skip
**După răspunsul lui Marius:**
- "ok X" → execut + marchez `[x]`
- "backlog X" → marchez `[→]` + adaug în backlog cu nivel + referință
- "nu X" → marchez `[—]`
- (ignoră) → marchez `[→]` + adaug în backlog "De revizuit"
**Structură backlog.md:**
- De executat = recomandate
- De revizuit = ignorate
- Vechi = > 30 zile
**Documentație completă:** `kb/projects/FLUX-JOBURI.md`
## Protocol cross-channel (OBLIGATORIU)
Când un agent trimite mesaj pe canalul MEU și așteaptă răspuns de la user:
→ Trebuie să-mi trimită și mie `sessions_send` cu contextul
Când EU trimit pe canalul altui agent:
1. Trimit mesajul cu `message` tool
2. **IMEDIAT DUPĂ**`sessions_send` către agentul destinatar cu:
- Ce am trimis (rezumat)
- Ce propuneri am făcut (numerotate)
- Ce răspuns aștept
Astfel știm toți contextul când userul răspunde.

View File

@@ -0,0 +1,41 @@
# Memory 2026-01-31
## Decizii mari azi
### Flux Joburi Complet Restructurat
- **Documentație:** `kb/projects/FLUX-JOBURI.md`
- morning-report + evening-report → **echo-work** (nu echo)
- morning-coaching + evening-coaching → echo-health
- Coaching verifică ultimele **7 zile** (nu 14)
### Sistem Insights + Backlog
- `[ ]` disponibil | `[x]` executat | `[→]` backlog | `[—]` skip
- Propuneri ignorate → backlog "De revizuit"
- Propuneri > 30 zile → propun curățare
- Backlog are: De executat, De revizuit, Vechi
### Coaching salvează cu referințe
- `kb/coaching/YYYY-MM-DD-dimineata.md`
- Include "Surse folosite" cu link-uri la note/insights
- NU marchează în insights (doar se inspiră)
### Protocol cross-channel
- Când trimiți pe canalul altui agent → sessions_send cu context
- Adăugat în AGENTS.md toți agenții
## Făcut azi
- ✅ Git commit + push (99 fișiere restructurare)
- ✅ Audit securitate Clawdbot (ok, 127.0.0.1)
- ✅ Creat fișe grup sprijin: blocare-deblocare, moment-greu-cadou, pentru-cine-altcineva
- ✅ Actualizat toate joburile cu noul sistem
- ✅ Actualizat AGENTS.md în echo-work, echo-health, root
- ✅ Creat kb/backlog.md cu structura nouă
- ✅ Creat kb/projects/FLUX-JOBURI.md documentație completă
## De reținut
- Rapoarte propun din insights (7 zile) + backlog (1-2 rotație)
- Marius vrea 80/20: propun tot, el decide
- Propunerile integrabile în flux = RECOMANDATE (nu respinse)
- Note din kb/coaching/ apar în notes.html (are .rules.json)

View File

@@ -0,0 +1,13 @@
# Reguli de comunicare
## Cross-agent messages
Când primesc mesaj de la alt agent (via sessions_send):
1. **Confirm IMEDIAT pe canal** - "Am primit de la [agent]: [rezumat]"
2. Spun ce fac: "Actualizez X / Verific Y"
3. Confirm când termin: "Done ✅"
Marius nu vede mesajele interne - trebuie să comunic transparent ce se întâmplă.
---
*Adăugat: 2026-01-31*

View File

@@ -102,6 +102,10 @@ class TaskBoardHandler(SimpleHTTPRequestHandler):
self.handle_git_status() self.handle_git_status()
elif self.path == '/api/agents' or self.path.startswith('/api/agents?'): elif self.path == '/api/agents' or self.path.startswith('/api/agents?'):
self.handle_agents_status() self.handle_agents_status()
elif self.path == '/api/cron' or self.path.startswith('/api/cron?'):
self.handle_cron_status()
elif self.path == '/api/activity' or self.path.startswith('/api/activity?'):
self.handle_activity()
elif self.path.startswith('/api/files'): elif self.path.startswith('/api/files'):
self.handle_files_get() self.handle_files_get()
elif self.path.startswith('/api/'): elif self.path.startswith('/api/'):
@@ -215,6 +219,215 @@ class TaskBoardHandler(SimpleHTTPRequestHandler):
except Exception as e: except Exception as e:
self.send_json({'error': str(e)}, 500) self.send_json({'error': str(e)}, 500)
def handle_cron_status(self):
"""Get cron jobs status from ~/.clawdbot/cron/jobs.json"""
try:
jobs_file = Path.home() / '.clawdbot' / 'cron' / 'jobs.json'
if not jobs_file.exists():
self.send_json({'jobs': [], 'error': 'No jobs file found'})
return
data = json.loads(jobs_file.read_text())
all_jobs = data.get('jobs', [])
# Filter enabled jobs and format for dashboard
now_ms = datetime.now().timestamp() * 1000
today_start = datetime.now().replace(hour=0, minute=0, second=0, microsecond=0)
today_start_ms = today_start.timestamp() * 1000
jobs = []
for job in all_jobs:
if not job.get('enabled', False):
continue
# Parse cron expression to get time
schedule = job.get('schedule', {})
expr = schedule.get('expr', '')
# Simple cron parsing for display - convert UTC to Bucharest
parts = expr.split()
if len(parts) >= 2:
minute = parts[0]
hour = parts[1]
if minute.isdigit() and (hour.isdigit() or '-' in hour):
# Handle hour ranges like "7-17"
if '-' in hour:
hour_start, hour_end = hour.split('-')
hour = hour_start # Show first hour
# Convert UTC to Bucharest (UTC+2 winter, UTC+3 summer)
from datetime import timezone as dt_timezone
from zoneinfo import ZoneInfo
try:
bucharest = ZoneInfo('Europe/Bucharest')
utc_hour = int(hour)
utc_minute = int(minute)
# Create UTC datetime for today
utc_dt = datetime.now(dt_timezone.utc).replace(hour=utc_hour, minute=utc_minute, second=0, microsecond=0)
local_dt = utc_dt.astimezone(bucharest)
time_str = f"{local_dt.hour:02d}:{local_dt.minute:02d}"
except:
time_str = f"{int(hour):02d}:{int(minute):02d}"
else:
time_str = expr[:15]
else:
time_str = expr[:15]
# Check if ran today
state = job.get('state', {})
last_run = state.get('lastRunAtMs', 0)
ran_today = last_run >= today_start_ms
last_status = state.get('lastStatus', 'unknown')
jobs.append({
'id': job.get('id'),
'name': job.get('name'),
'agentId': job.get('agentId'),
'time': time_str,
'schedule': expr,
'ranToday': ran_today,
'lastStatus': last_status if ran_today else None,
'lastRunAtMs': last_run,
'nextRunAtMs': state.get('nextRunAtMs')
})
# Sort by time
jobs.sort(key=lambda j: j['time'])
self.send_json({
'jobs': jobs,
'total': len(jobs),
'ranToday': sum(1 for j in jobs if j['ranToday'])
})
except Exception as e:
self.send_json({'error': str(e)}, 500)
def handle_activity(self):
"""Aggregate activity from multiple sources: cron jobs, git commits, file changes."""
from datetime import timezone as dt_timezone
from zoneinfo import ZoneInfo
try:
activities = []
bucharest = ZoneInfo('Europe/Bucharest')
workspace = Path('/home/moltbot/clawd')
# 1. Cron jobs ran today
try:
result = subprocess.run(
['clawdbot', 'cron', 'list', '--json'],
capture_output=True, text=True, timeout=10
)
if result.returncode == 0:
cron_data = json.loads(result.stdout)
today_start = datetime.now().replace(hour=0, minute=0, second=0, microsecond=0)
today_start_ms = today_start.timestamp() * 1000
for job in cron_data.get('jobs', []):
state = job.get('state', {})
last_run = state.get('lastRunAtMs', 0)
if last_run >= today_start_ms:
run_time = datetime.fromtimestamp(last_run / 1000, tz=dt_timezone.utc)
local_time = run_time.astimezone(bucharest)
activities.append({
'type': 'cron',
'icon': 'clock',
'text': f"Job: {job.get('name', 'unknown')}",
'agent': job.get('agentId', 'echo'),
'time': local_time.strftime('%H:%M'),
'timestamp': last_run,
'status': state.get('lastStatus', 'ok')
})
except:
pass
# 2. Git commits (last 24h)
try:
result = subprocess.run(
['git', 'log', '--oneline', '--since=24 hours ago', '--format=%H|%s|%at'],
cwd=workspace, capture_output=True, text=True, timeout=10
)
if result.returncode == 0:
for line in result.stdout.strip().split('\n'):
if '|' in line:
parts = line.split('|')
if len(parts) >= 3:
commit_hash, message, timestamp = parts[0], parts[1], int(parts[2])
commit_time = datetime.fromtimestamp(timestamp, tz=dt_timezone.utc)
local_time = commit_time.astimezone(bucharest)
activities.append({
'type': 'git',
'icon': 'git-commit',
'text': message[:60] + ('...' if len(message) > 60 else ''),
'agent': 'git',
'time': local_time.strftime('%H:%M'),
'timestamp': timestamp * 1000
})
except:
pass
# 3. Recent files in kb/ (last 24h)
try:
kb_dir = workspace / 'kb'
cutoff = datetime.now().timestamp() - (24 * 3600)
for md_file in kb_dir.rglob('*.md'):
stat = md_file.stat()
if stat.st_mtime > cutoff:
file_time = datetime.fromtimestamp(stat.st_mtime, tz=dt_timezone.utc)
local_time = file_time.astimezone(bucharest)
rel_path = md_file.relative_to(workspace)
activities.append({
'type': 'file',
'icon': 'file-text',
'text': f"Fișier: {md_file.name}",
'agent': str(rel_path.parent),
'time': local_time.strftime('%H:%M'),
'timestamp': int(stat.st_mtime * 1000),
'path': str(rel_path)
})
except:
pass
# 4. Tasks from tasks.json
try:
tasks_file = workspace / 'dashboard' / 'tasks.json'
if tasks_file.exists():
tasks_data = json.loads(tasks_file.read_text())
for col in tasks_data.get('columns', []):
for task in col.get('tasks', []):
ts_str = task.get('completed') or task.get('created', '')
if ts_str:
try:
ts = datetime.fromisoformat(ts_str.replace('Z', '+00:00'))
if ts.timestamp() > (datetime.now().timestamp() - 7 * 24 * 3600):
local_time = ts.astimezone(bucharest)
activities.append({
'type': 'task',
'icon': 'check-circle' if task.get('completed') else 'circle',
'text': task.get('title', ''),
'agent': task.get('agent', 'Echo'),
'time': local_time.strftime('%d %b %H:%M'),
'timestamp': int(ts.timestamp() * 1000),
'status': 'done' if task.get('completed') else col['id']
})
except:
pass
except:
pass
# Sort by timestamp descending
activities.sort(key=lambda x: x.get('timestamp', 0), reverse=True)
# Limit to 30 items
activities = activities[:30]
self.send_json({
'activities': activities,
'total': len(activities)
})
except Exception as e:
self.send_json({'error': str(e)}, 500)
def handle_files_get(self): def handle_files_get(self):
"""List files or get file content.""" """List files or get file content."""
from urllib.parse import urlparse, parse_qs from urllib.parse import urlparse, parse_qs
@@ -259,12 +472,12 @@ class TaskBoardHandler(SimpleHTTPRequestHandler):
items = [] items = []
try: try:
for item in sorted(target.iterdir()): for item in sorted(target.iterdir()):
if item.name.startswith('.'): stat = item.stat()
continue
items.append({ items.append({
'name': item.name, 'name': item.name,
'type': 'dir' if item.is_dir() else 'file', 'type': 'dir' if item.is_dir() else 'file',
'size': item.stat().st_size if item.is_file() else None, 'size': stat.st_size if item.is_file() else None,
'mtime': stat.st_mtime,
'path': str(item.relative_to(workspace)) 'path': str(item.relative_to(workspace))
}) })
self.send_json({ self.send_json({
@@ -314,6 +527,9 @@ class TaskBoardHandler(SimpleHTTPRequestHandler):
self.send_response(code) self.send_response(code)
self.send_header('Content-Type', 'application/json') self.send_header('Content-Type', 'application/json')
self.send_header('Access-Control-Allow-Origin', '*') self.send_header('Access-Control-Allow-Origin', '*')
self.send_header('Cache-Control', 'no-cache, no-store, must-revalidate')
self.send_header('Pragma', 'no-cache')
self.send_header('Expires', '0')
self.end_headers() self.end_headers()
self.wfile.write(json.dumps(data).encode()) self.wfile.write(json.dumps(data).encode())

View File

@@ -102,6 +102,149 @@
height: 16px; height: 16px;
} }
.sort-select {
background: transparent;
border: none;
color: var(--text-secondary);
font-size: var(--text-sm);
padding: var(--space-1) var(--space-2);
cursor: pointer;
outline: none;
}
.sort-select option {
background: var(--bg-base);
color: var(--text-primary);
}
/* ========== LIST VIEW - Windows Explorer style ========== */
.file-grid.view-list {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
gap: var(--space-1);
}
.file-grid.view-list .file-item {
flex-direction: row;
padding: var(--space-1) var(--space-2);
gap: var(--space-2);
background: transparent;
border: none;
}
.file-grid.view-list .file-item:hover {
background: var(--bg-surface-hover);
}
.file-grid.view-list .file-icon {
width: 16px;
height: 16px;
flex-shrink: 0;
}
.file-grid.view-list .file-icon svg {
width: 16px;
height: 16px;
}
.file-grid.view-list .file-name {
font-size: var(--text-sm);
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.file-grid.view-list .file-meta {
display: none;
}
/* ========== DETAILS VIEW - Windows Explorer style with columns ========== */
.file-grid.view-details {
display: flex;
flex-direction: column;
gap: 0;
}
.file-grid.view-details .file-header {
display: grid;
grid-template-columns: 24px 1fr 100px 80px 120px;
align-items: center;
padding: var(--space-2) var(--space-3);
gap: var(--space-3);
background: var(--bg-surface);
border-bottom: 2px solid var(--border);
font-size: var(--text-xs);
font-weight: 600;
color: var(--text-muted);
position: sticky;
top: 0;
}
.file-grid.view-details .file-header span {
cursor: pointer;
}
.file-grid.view-details .file-header span:hover {
color: var(--text-primary);
}
.file-grid.view-details .file-item {
display: grid;
grid-template-columns: 24px 1fr 100px 80px 120px;
align-items: center;
padding: var(--space-2) var(--space-3);
gap: var(--space-3);
background: transparent;
border: none;
border-bottom: 1px solid var(--border);
border-radius: 0;
}
.file-grid.view-details .file-item:hover {
background: var(--bg-surface-hover);
}
.file-grid.view-details .file-icon {
width: 18px;
height: 18px;
}
.file-grid.view-details .file-icon svg {
width: 18px;
height: 18px;
}
.file-grid.view-details .file-name {
font-size: var(--text-sm);
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
text-align: left;
}
.file-grid.view-details .file-meta {
display: contents;
}
.file-grid.view-details .file-type,
.file-grid.view-details .file-size,
.file-grid.view-details .file-date {
font-size: var(--text-xs);
color: var(--text-muted);
white-space: nowrap;
}
.file-grid.view-details .file-type {
text-transform: uppercase;
}
/* ========== TILES VIEW - Original grid style ========== */
.file-grid.view-tiles {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));
gap: var(--space-3);
}
/* Content area */ /* Content area */
.content-area { .content-area {
flex: 1; flex: 1;
@@ -269,6 +412,8 @@
#markdownPreview code { background: var(--bg-surface); padding: 2px 6px; border-radius: 4px; font-family: var(--font-mono); } #markdownPreview code { background: var(--bg-surface); padding: 2px 6px; border-radius: 4px; font-family: var(--font-mono); }
#markdownPreview pre { background: var(--bg-surface); padding: 1em; border-radius: 8px; overflow-x: auto; } #markdownPreview pre { background: var(--bg-surface); padding: 1em; border-radius: 8px; overflow-x: auto; }
#markdownPreview blockquote { border-left: 3px solid var(--accent); padding-left: 1em; margin-left: 0; color: var(--text-muted); } #markdownPreview blockquote { border-left: 3px solid var(--accent); padding-left: 1em; margin-left: 0; color: var(--text-muted); }
#markdownPreview a, #markdownPreview .file-link { color: var(--accent); text-decoration: none; }
#markdownPreview a:hover, #markdownPreview .file-link:hover { text-decoration: underline; }
.preview-active #codeEditor { display: none; } .preview-active #codeEditor { display: none; }
.preview-active #markdownPreview { display: block; } .preview-active #markdownPreview { display: block; }
@@ -348,9 +493,36 @@
<span class="breadcrumb-item current" onclick="loadPath('')">~/clawd</span> <span class="breadcrumb-item current" onclick="loadPath('')">~/clawd</span>
</div> </div>
<div class="toolbar-actions"> <div class="toolbar-actions">
<!-- View Mode Toggle -->
<div class="view-toggle" id="viewModeToggle">
<button class="view-btn" data-view="list" onclick="setViewMode('list')" title="Listă">
<i data-lucide="list"></i>
</button>
<button class="view-btn" data-view="details" onclick="setViewMode('details')" title="Detalii">
<i data-lucide="layout-list"></i>
</button>
<button class="view-btn active" data-view="tiles" onclick="setViewMode('tiles')" title="Tiles">
<i data-lucide="layout-grid"></i>
</button>
</div>
<!-- Sort Toggle -->
<div class="view-toggle">
<select class="sort-select" id="sortBy" onchange="sortFiles()">
<option value="name">Nume</option>
<option value="type">Tip</option>
<option value="size">Mărime</option>
<option value="date">Dată</option>
</select>
<button class="view-btn" id="sortDirBtn" onclick="toggleSortDir()" title="Ordine">
<i data-lucide="arrow-down-a-z" id="sortDirIcon"></i>
</button>
</div>
<!-- Browse/Editor Toggle -->
<div class="view-toggle"> <div class="view-toggle">
<button class="view-btn active" id="browseBtn" onclick="showBrowse()" title="Browse"> <button class="view-btn active" id="browseBtn" onclick="showBrowse()" title="Browse">
<i data-lucide="layout-grid"></i> <i data-lucide="folder"></i>
</button> </button>
<button class="view-btn" id="editorBtn" onclick="showEditor()" title="Editor"> <button class="view-btn" id="editorBtn" onclick="showEditor()" title="Editor">
<i data-lucide="code"></i> <i data-lucide="code"></i>
@@ -435,6 +607,73 @@
let currentFile = null; let currentFile = null;
let originalContent = ''; let originalContent = '';
let isModified = false; let isModified = false;
let currentViewMode = localStorage.getItem('filesViewMode') || 'tiles';
let currentSortBy = localStorage.getItem('filesSortBy') || 'name';
let currentSortDir = localStorage.getItem('filesSortDir') || 'asc';
let currentItems = [];
// Initialize view mode
function initViewMode() {
setViewMode(currentViewMode, false);
document.getElementById('sortBy').value = currentSortBy;
updateSortIcon();
}
function setViewMode(mode, reload = true) {
currentViewMode = mode;
localStorage.setItem('filesViewMode', mode);
// Update buttons
document.querySelectorAll('#viewModeToggle .view-btn').forEach(btn => {
btn.classList.toggle('active', btn.dataset.view === mode);
});
// Update grid class
const grid = document.getElementById('fileGrid');
grid.classList.remove('view-list', 'view-details', 'view-tiles');
grid.classList.add('view-' + mode);
if (reload && currentItems.length > 0) {
renderFileGrid(currentItems);
}
}
function sortFiles() {
currentSortBy = document.getElementById('sortBy').value;
localStorage.setItem('filesSortBy', currentSortBy);
if (currentItems.length > 0) {
renderFileGrid(currentItems);
}
}
function setSortBy(field) {
if (currentSortBy === field) {
toggleSortDir();
} else {
currentSortBy = field;
document.getElementById('sortBy').value = field;
localStorage.setItem('filesSortBy', currentSortBy);
if (currentItems.length > 0) {
renderFileGrid(currentItems);
}
}
}
function toggleSortDir() {
currentSortDir = currentSortDir === 'asc' ? 'desc' : 'asc';
localStorage.setItem('filesSortDir', currentSortDir);
updateSortIcon();
if (currentItems.length > 0) {
renderFileGrid(currentItems);
}
}
function updateSortIcon() {
const icon = document.getElementById('sortDirIcon');
const iconName = currentSortDir === 'asc' ? 'arrow-down-a-z' : 'arrow-up-z-a';
icon.setAttribute('data-lucide', iconName);
lucide.createIcons();
}
function showBrowse() { function showBrowse() {
if (isModified && !confirm('Ai modificări nesalvate. Continui?')) return; if (isModified && !confirm('Ai modificări nesalvate. Continui?')) return;
@@ -498,7 +737,12 @@
} }
function renderFileGrid(items) { function renderFileGrid(items) {
// Store items for re-rendering on view/sort change
currentItems = items;
const grid = document.getElementById('fileGrid'); const grid = document.getElementById('fileGrid');
grid.classList.remove('view-list', 'view-details', 'view-tiles');
grid.classList.add('view-' + currentViewMode);
if (items.length === 0) { if (items.length === 0) {
grid.innerHTML = ` grid.innerHTML = `
@@ -511,20 +755,82 @@
return; return;
} }
items.sort((a, b) => { // Sort items
const getExt = (name) => name.includes('.') ? name.split('.').pop().toLowerCase() : '';
const sorted = [...items].sort((a, b) => {
// Directories always first
if (a.type !== b.type) return a.type === 'dir' ? -1 : 1; if (a.type !== b.type) return a.type === 'dir' ? -1 : 1;
return a.name.localeCompare(b.name);
let cmp = 0;
if (currentSortBy === 'name') {
cmp = a.name.localeCompare(b.name);
} else if (currentSortBy === 'date') {
cmp = (a.mtime || 0) - (b.mtime || 0);
} else if (currentSortBy === 'size') {
cmp = (a.size || 0) - (b.size || 0);
} else if (currentSortBy === 'type') {
cmp = getExt(a.name).localeCompare(getExt(b.name));
}
return currentSortDir === 'asc' ? cmp : -cmp;
}); });
grid.innerHTML = items.map(item => ` // Add header for details view
<div class="file-item ${currentFile === item.path ? 'active' : ''}" onclick="handleClick('${item.path}', '${item.type}')"> let headerHtml = '';
<div class="file-icon ${item.type === 'dir' ? 'folder' : ''}"> if (currentViewMode === 'details') {
<i data-lucide="${item.type === 'dir' ? 'folder' : getFileIcon(item.name)}"></i> const arrow = (field) => currentSortBy === field ? (currentSortDir === 'asc' ? '' : ' ▼') : '';
headerHtml = `
<div class="file-header">
<span></span>
<span onclick="setSortBy('name')" style="cursor:pointer">Nume${arrow('name')}</span>
<span onclick="setSortBy('type')" style="cursor:pointer">Tip${arrow('type')}</span>
<span onclick="setSortBy('size')" style="cursor:pointer">Mărime${arrow('size')}</span>
<span onclick="setSortBy('date')" style="cursor:pointer">Dată${arrow('date')}</span>
</div> </div>
<div class="file-name">${item.name}</div> `;
${item.size ? `<div class="file-size">${formatSize(item.size)}</div>` : ''} }
</div>
`).join(''); grid.innerHTML = headerHtml + sorted.map(item => {
const dateStr = item.mtime ? new Date(item.mtime * 1000).toLocaleString('ro-RO', {
day: '2-digit', month: 'short', hour: '2-digit', minute: '2-digit'
}) : '';
const fileType = item.type === 'dir' ? 'Folder' : getFileType(item.name);
const sizeStr = item.size !== undefined ? formatSize(item.size) : '-';
if (currentViewMode === 'details') {
return `
<div class="file-item ${currentFile === item.path ? 'active' : ''}" onclick="handleClick('${item.path}', '${item.type}')">
<div class="file-icon ${item.type === 'dir' ? 'folder' : ''}">
<i data-lucide="${item.type === 'dir' ? 'folder' : getFileIcon(item.name)}"></i>
</div>
<div class="file-name">${item.name}</div>
<div class="file-meta">
<span class="file-type">${fileType}</span>
<span class="file-size">${sizeStr}</span>
<span class="file-date">${dateStr || '-'}</span>
</div>
</div>
`;
} else if (currentViewMode === 'list') {
return `
<div class="file-item ${currentFile === item.path ? 'active' : ''}" onclick="handleClick('${item.path}', '${item.type}')">
<div class="file-icon ${item.type === 'dir' ? 'folder' : ''}">
<i data-lucide="${item.type === 'dir' ? 'folder' : getFileIcon(item.name)}"></i>
</div>
<div class="file-name">${item.name}</div>
</div>
`;
} else {
// Tiles view - original style
return `
<div class="file-item ${currentFile === item.path ? 'active' : ''}" onclick="handleClick('${item.path}', '${item.type}')">
<div class="file-icon ${item.type === 'dir' ? 'folder' : ''}">
<i data-lucide="${item.type === 'dir' ? 'folder' : getFileIcon(item.name)}"></i>
</div>
<div class="file-name">${item.name}</div>
</div>
`;
}
}).join('');
lucide.createIcons(); lucide.createIcons();
} }
@@ -549,6 +855,26 @@
return icons[ext] || 'file'; return icons[ext] || 'file';
} }
function getFileType(name) {
const ext = name.split('.').pop().toLowerCase();
const types = {
'md': 'Markdown',
'txt': 'Text',
'json': 'JSON',
'js': 'JavaScript',
'py': 'Python',
'html': 'HTML',
'css': 'CSS',
'sh': 'Shell',
'yml': 'YAML',
'yaml': 'YAML',
'log': 'Log',
'xsd': 'XML Schema',
'pdf': 'PDF'
};
return types[ext] || ext.toUpperCase();
}
function formatSize(bytes) { function formatSize(bytes) {
if (bytes < 1024) return bytes + ' B'; if (bytes < 1024) return bytes + ' B';
if (bytes < 1024 * 1024) return (bytes / 1024).toFixed(1) + ' KB'; if (bytes < 1024 * 1024) return (bytes / 1024).toFixed(1) + ' KB';
@@ -701,6 +1027,7 @@
}); });
// Init // Init
initViewMode();
loadPath(getPathFromURL()); loadPath(getPathFromURL());
</script> </script>
</body> </body>

View File

@@ -498,7 +498,7 @@
flex-shrink: 0; flex-shrink: 0;
} }
.activity-icon.done { .activity-icon.done, .activity-icon.task {
background: rgba(34, 197, 94, 0.2); background: rgba(34, 197, 94, 0.2);
color: #22c55e; color: #22c55e;
} }
@@ -508,11 +508,33 @@
color: #3b82f6; color: #3b82f6;
} }
.activity-icon.cron {
background: rgba(168, 85, 247, 0.2);
color: #a855f7;
}
.activity-icon.git {
background: rgba(249, 115, 22, 0.2);
color: #f97316;
}
.activity-icon.file {
background: rgba(20, 184, 166, 0.2);
color: #14b8a6;
}
.activity-icon svg { .activity-icon svg {
width: 14px; width: 14px;
height: 14px; height: 14px;
} }
.activity-type {
font-size: var(--text-xs);
padding: 2px 6px;
border-radius: 4px;
background: var(--bg-surface);
}
.activity-content { .activity-content {
flex: 1; flex: 1;
min-width: 0; min-width: 0;
@@ -732,6 +754,7 @@
} }
.issue-owner.marius { color: #22c55e; } .issue-owner.marius { color: #22c55e; }
.issue-owner.robert { color: #f59e0b; }
.issue-owner.clawdbot { color: #8b5cf6; } .issue-owner.clawdbot { color: #8b5cf6; }
.issue-date { .issue-date {
@@ -786,7 +809,7 @@
} }
.modal { .modal {
background: var(--bg-surface); background: var(--bg-base);
border: 1px solid var(--border); border: 1px solid var(--border);
border-radius: var(--radius-lg); border-radius: var(--radius-lg);
padding: var(--space-5); padding: var(--space-5);
@@ -794,6 +817,7 @@
max-width: 500px; max-width: 500px;
max-height: 90vh; max-height: 90vh;
overflow-y: auto; overflow-y: auto;
box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.5);
} }
.modal-title { .modal-title {
@@ -978,28 +1002,28 @@
<!-- Stats Summary --> <!-- Stats Summary -->
<div class="stats-summary" id="statsSummary"> <div class="stats-summary" id="statsSummary">
<div class="stat-card"> <div class="stat-card" title="Task-uri completate azi">
<div class="stat-icon"><i data-lucide="check-circle"></i></div> <div class="stat-icon"><i data-lucide="check-circle"></i></div>
<div class="stat-content"> <div class="stat-content">
<div class="stat-value" id="statToday">0</div> <div class="stat-value" id="statToday">0</div>
<div class="stat-label">Azi</div> <div class="stat-label">Tasks azi</div>
</div> </div>
</div> </div>
<div class="stat-card"> <div class="stat-card" title="Task-uri completate săptămâna aceasta">
<div class="stat-icon"><i data-lucide="calendar"></i></div> <div class="stat-icon"><i data-lucide="calendar"></i></div>
<div class="stat-content"> <div class="stat-content">
<div class="stat-value" id="statWeek">0</div> <div class="stat-value" id="statWeek">0</div>
<div class="stat-label">Săptămâna</div> <div class="stat-label">Tasks săpt.</div>
</div> </div>
</div> </div>
<div class="stat-card"> <div class="stat-card" title="Task-uri completate luna aceasta">
<div class="stat-icon"><i data-lucide="trending-up"></i></div> <div class="stat-icon"><i data-lucide="trending-up"></i></div>
<div class="stat-content"> <div class="stat-content">
<div class="stat-value" id="statMonth">0</div> <div class="stat-value" id="statMonth">0</div>
<div class="stat-label">Luna</div> <div class="stat-label">Tasks lună</div>
</div> </div>
</div> </div>
<div class="stat-card"> <div class="stat-card" title="Număr de fișiere insights">
<div class="stat-icon"><i data-lucide="lightbulb"></i></div> <div class="stat-icon"><i data-lucide="lightbulb"></i></div>
<div class="stat-content"> <div class="stat-content">
<div class="stat-value" id="statInsights">0</div> <div class="stat-value" id="statInsights">0</div>
@@ -1055,6 +1079,7 @@
<div class="issues-filters" id="issuesFilters"> <div class="issues-filters" id="issuesFilters">
<button class="filter-btn active" data-filter="all">Toate</button> <button class="filter-btn active" data-filter="all">Toate</button>
<button class="filter-btn" data-filter="marius">👤 Marius</button> <button class="filter-btn" data-filter="marius">👤 Marius</button>
<button class="filter-btn" data-filter="robert">👷 Robert</button>
<button class="filter-btn" data-filter="clawdbot">🤖 Clawdbot</button> <button class="filter-btn" data-filter="clawdbot">🤖 Clawdbot</button>
</div> </div>
<div class="panel-body" id="issuesBody"> <div class="panel-body" id="issuesBody">
@@ -1090,6 +1115,7 @@
<label class="form-label">Owner</label> <label class="form-label">Owner</label>
<select class="input" id="issueOwner"> <select class="input" id="issueOwner">
<option value="marius">👤 Marius</option> <option value="marius">👤 Marius</option>
<option value="robert">👷 Robert</option>
<option value="clawdbot">🤖 Clawdbot</option> <option value="clawdbot">🤖 Clawdbot</option>
</select> </select>
</div> </div>
@@ -1343,42 +1369,53 @@
} }
async function loadCronStatus() { async function loadCronStatus() {
const now = new Date(); try {
const hour = now.getHours(); const response = await fetch('./api/cron?' + Date.now());
if (!response.ok) throw new Error('API error');
// TODO: În viitor, fetch din /api/cron const data = await response.json();
const jobs = [
{ time: '06:30', name: 'morning-report', done: hour >= 7 }, const jobs = data.jobs || [];
{ time: '07:00', name: 'morning-coaching', done: hour >= 7 }, const ranToday = data.ranToday || 0;
{ time: '18:00', name: 'evening-report', done: hour >= 18 },
{ time: '19:00', name: 'evening-coaching', done: hour >= 19 } // Update badge
]; const badge = document.getElementById('cronBadge');
badge.textContent = `${ranToday}/${jobs.length}`;
const doneCount = jobs.filter(j => j.done).length; badge.className = 'status-badge ok';
// Update badge // Update subtitle - find next job to run
const badge = document.getElementById('cronBadge'); const subtitle = document.getElementById('cronSubtitle');
badge.textContent = `${doneCount}/${jobs.length}`; const now = Date.now();
badge.className = 'status-badge ok'; const pendingJobs = jobs.filter(j => !j.ranToday);
const nextJob = pendingJobs.length > 0 ? pendingJobs[0] : null;
// Update subtitle subtitle.textContent = nextJob
const subtitle = document.getElementById('cronSubtitle'); ? `Următorul: ${nextJob.time} ${nextJob.name}`
const nextJob = jobs.find(j => !j.done); : 'Toate job-urile au rulat azi';
subtitle.textContent = nextJob
? `Următorul: ${nextJob.time} ${nextJob.name}` // Update details
: 'Toate job-urile au rulat azi'; const details = document.getElementById('cronDetails');
details.innerHTML = jobs.map(job => {
// Update details const done = job.ranToday;
const details = document.getElementById('cronDetails'); const failed = job.lastStatus === 'error';
details.innerHTML = jobs.map(job => ` const statusClass = failed ? 'failed' : (done ? 'done' : 'pending');
<div class="cron-item ${job.done ? 'done' : 'pending'}"> const icon = failed ? 'x-circle' : (done ? 'check-circle' : 'clock');
<i data-lucide="${job.done ? 'check-circle' : 'clock'}" class="cron-icon ${job.done ? 'done' : 'pending'}"></i>
<span class="cron-time">${job.time}</span> return `
<span class="cron-name">${job.name}</span> <div class="cron-item ${statusClass}">
</div> <i data-lucide="${icon}" class="cron-icon ${statusClass}"></i>
`).join(''); <span class="cron-time">${job.time}</span>
<span class="cron-name">${job.name}</span>
lucide.createIcons(); <span class="cron-agent" style="color: var(--text-muted); font-size: 0.75rem; margin-left: auto;">${job.agentId || ''}</span>
</div>
`;
}).join('');
lucide.createIcons();
} catch (e) {
console.error('Error loading cron status:', e);
const badge = document.getElementById('cronBadge');
badge.textContent = 'eroare';
badge.className = 'status-badge error';
}
} }
async function loadAgentsStatus() { async function loadAgentsStatus() {
@@ -1461,30 +1498,22 @@
async function loadActivity() { async function loadActivity() {
try { try {
// Fetch from tasks.json // Fetch from unified activity API
const response = await fetch('tasks.json?t=' + Date.now()); const response = await fetch('./api/activity?t=' + Date.now());
const data = await response.json(); const data = await response.json();
// Collect all tasks from all columns with their status if (data.error) throw new Error(data.error);
let allTasks = [];
data.columns.forEach(col => {
col.tasks.forEach(task => {
const timestamp = task.completed || task.created || '';
allTasks.push({
type: col.id === 'done' ? 'done' : (col.id === 'in-progress' ? 'running' : 'pending'),
text: task.title,
agent: task.agent || 'Echo',
time: formatActivityTime(timestamp),
timestamp: new Date(timestamp).getTime() || 0
});
});
});
// Sort descending by timestamp (newest first) activityData = (data.activities || []).map(a => ({
allTasks.sort((a, b) => b.timestamp - a.timestamp); type: a.type,
icon: a.icon || 'activity',
// Take only recent items (last 20) text: a.text,
activityData = allTasks.slice(0, 20); agent: a.agent || 'Echo',
time: a.time,
timestamp: a.timestamp,
status: a.status,
path: a.path
}));
} catch (e) { } catch (e) {
console.error('Failed to load activity:', e); console.error('Failed to load activity:', e);
@@ -1574,28 +1603,32 @@
const today = new Date().toLocaleDateString('ro-RO', { day: 'numeric', month: 'short' }); const today = new Date().toLocaleDateString('ro-RO', { day: 'numeric', month: 'short' });
// Group by type for better display
const typeLabels = {
'cron': '⏰ Cron Jobs',
'git': '📦 Git Commits',
'file': '📄 Fișiere',
'task': '✅ Task-uri'
};
body.innerHTML = ` body.innerHTML = `
<div class="activity-section"> <div class="activity-section">
<div class="activity-section-title"> <div class="activity-section-title">
<i data-lucide="calendar"></i> <i data-lucide="activity"></i>
Azi (${today}) Ultimele 24h
</div> </div>
${activityData.map(item => ` ${activityData.map(item => `
<div class="activity-item"> <div class="activity-item" ${item.path ? `onclick="window.open('files.html#${item.path}', '_blank')" style="cursor:pointer"` : ''}>
<div class="activity-icon ${item.type}"> <div class="activity-icon ${item.type}">
<i data-lucide="${item.type === 'running' ? 'loader' : 'check'}"></i> <i data-lucide="${item.icon || 'activity'}"></i>
</div> </div>
<div class="activity-content"> <div class="activity-content">
<div class="activity-text">${item.text}</div> <div class="activity-text">${item.text}</div>
<div class="activity-meta"> <div class="activity-meta">
<span class="activity-type">${typeLabels[item.type] || item.type}</span>
<span class="activity-agent">${item.agent}</span> <span class="activity-agent">${item.agent}</span>
<span>${item.time}</span> <span>${item.time}</span>
</div> </div>
${item.progress ? `
<div class="progress-bar">
<div class="progress-fill" style="width: ${item.progress}%"></div>
</div>
` : ''}
</div> </div>
</div> </div>
`).join('')} `).join('')}
@@ -1683,7 +1716,8 @@
function renderIssueItem(issue) { function renderIssueItem(issue) {
const isDone = issue.status === 'done'; const isDone = issue.status === 'done';
const ownerIcon = issue.owner === 'clawdbot' ? '🤖' : '👤'; const ownerIcons = { 'clawdbot': '🤖', 'robert': '👷', 'marius': '👤' };
const ownerIcon = ownerIcons[issue.owner] || '👤';
const dateStr = new Date(issue.created).toLocaleDateString('ro-RO', { day: 'numeric', month: 'short' }); const dateStr = new Date(issue.created).toLocaleDateString('ro-RO', { day: 'numeric', month: 'short' });
return ` return `
@@ -1695,7 +1729,7 @@
<div class="issue-title">${issue.title}</div> <div class="issue-title">${issue.title}</div>
<div class="issue-meta"> <div class="issue-meta">
${issue.program ? `<span class="issue-tag program">${issue.program}</span>` : ''} ${issue.program ? `<span class="issue-tag program">${issue.program}</span>` : ''}
<span class="issue-owner ${issue.owner}">${ownerIcon} ${issue.owner === 'clawdbot' ? 'Clawdbot' : 'Marius'}</span> <span class="issue-owner ${issue.owner}">${ownerIcon} ${issue.owner === 'clawdbot' ? 'Clawdbot' : (issue.owner === 'robert' ? 'Robert' : 'Marius')}</span>
<span class="issue-date">${dateStr}</span> <span class="issue-date">${dateStr}</span>
</div> </div>
</div> </div>

View File

@@ -152,6 +152,25 @@
font-weight: 600; font-weight: 600;
color: var(--text-primary); color: var(--text-primary);
line-height: 1.4; line-height: 1.4;
display: flex;
align-items: center;
gap: var(--space-2);
}
.note-file-link {
opacity: 0.4;
transition: opacity var(--transition-fast);
flex-shrink: 0;
}
.note-file-link:hover {
opacity: 1;
}
.note-file-link svg {
width: 14px;
height: 14px;
color: var(--text-muted);
} }
.note-tags { .note-tags {
@@ -226,17 +245,37 @@
border-bottom: 1px solid var(--border); border-bottom: 1px solid var(--border);
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
align-items: center; align-items: flex-start;
gap: var(--space-3);
position: sticky; position: sticky;
top: 0; top: 0;
background: var(--bg-base); background: var(--bg-base);
z-index: 10; z-index: 10;
flex-wrap: wrap;
} }
.note-viewer-header h2 { .note-viewer-header h2 {
font-size: var(--text-lg); font-size: var(--text-lg);
color: var(--text-primary); color: var(--text-primary);
font-weight: 600; font-weight: 600;
flex: 1;
min-width: 200px;
}
.viewer-path {
font-size: var(--text-xs);
color: var(--text-muted);
font-family: var(--font-mono);
text-decoration: none;
opacity: 0.7;
transition: opacity var(--transition-fast);
flex: 1;
min-width: 200px;
}
.viewer-path:hover {
opacity: 1;
color: var(--accent);
} }
.note-viewer-body { .note-viewer-body {
@@ -702,6 +741,7 @@
<div class="note-viewer-content"> <div class="note-viewer-content">
<div class="note-viewer-header"> <div class="note-viewer-header">
<h2 id="viewerTitle">Titlu</h2> <h2 id="viewerTitle">Titlu</h2>
<a id="viewerPath" href="#" class="viewer-path" target="_blank"></a>
<button class="btn btn-ghost" onclick="closeNote()"> <button class="btn btn-ghost" onclick="closeNote()">
<i data-lucide="x"></i> <i data-lucide="x"></i>
</button> </button>
@@ -1122,9 +1162,16 @@
tagsHtml tagsHtml
].filter(Boolean).join(''); ].filter(Boolean).join('');
// Convert notes-data/ to kb/ for files.html links
const filesPath = note.file.replace(/^notes-data\//, 'kb/');
return ` return `
<div class="note-card" onclick="openNote('${note.file}')"> <div class="note-card" onclick="openNote('${note.file}')">
<div class="note-title">${note.title}</div> <div class="note-title">
${note.title}
<a href="files.html#${filesPath}" class="note-file-link" onclick="event.stopPropagation()" title="${filesPath}">
<i data-lucide="external-link"></i>
</a>
</div>
<div class="note-tags">${allTags}</div> <div class="note-tags">${allTags}</div>
</div> </div>
`; `;
@@ -1140,6 +1187,11 @@
if (!note) return; if (!note) return;
document.getElementById('viewerTitle').textContent = note.title; document.getElementById('viewerTitle').textContent = note.title;
const pathEl = document.getElementById('viewerPath');
// Convert notes-data/ to kb/ for display and links
const filesPath = note.file.replace(/^notes-data\//, 'kb/');
pathEl.textContent = filesPath;
pathEl.href = 'files.html#' + filesPath;
document.getElementById('viewerContent').innerHTML = '<p style="color: var(--text-muted)">Se încarcă...</p>'; document.getElementById('viewerContent').innerHTML = '<p style="color: var(--text-muted)">Se încarcă...</p>';
document.getElementById('noteViewer').classList.add('active'); document.getElementById('noteViewer').classList.add('active');
document.body.style.overflow = 'hidden'; document.body.style.overflow = 'hidden';

View File

@@ -1,62 +1,46 @@
# Backlog - Propuneri pentru viitor # Backlog
**Tags:** @work @health @growth @sprijin @scout #backlog #propuneri **Actualizat:** 2026-01-31
Propuneri păstrate pentru viitor. Format: `[ ]` de făcut, `[x]` făcut, `[—]` renunțat.
--- ---
## ⚡ Urgent + Important ## De executat (recomandate, când ai timp)
*Gol momentan - se adaugă din insights când zici "azi prioritar"* *Propuneri aprobate pentru mai târziu sau recomandate din rapoarte*
<!-- Exemplu:
- [ ] ⚡ Titlu propunere - RECOMANDAT - [insights/2026-01-31.md]
-->
--- ---
## 📌 Important ## De revizuit (ignorate din rapoarte)
### @work *Propuneri la care nu ai răspuns - de decis: execut, șterg, sau las*
- [ ] Verificare securitate Clawdbot (port, trustedProxies)
### @growth <!-- Exemplu:
- [ ] Exercițiu Priming în morning-coaching (3 recunoștințe) - [ ] 📌 Titlu propunere - NERECOMANDAT (motiv) - [insights/2026-01-31.md]
-->
### @sprijin
- [ ] Fișă "blocare vs deblocare" cu exercițiu fiziologie
--- ---
## 💡 Nice-to-have ## Vechi (> 30 zile, de curățat)
### @work *Propuneri vechi - raportul va propune curățarea periodică*
- [ ] Template spec-driven development în kb/projects/
- [ ] Job proactive coding noaptea (ora 23)
- [ ] Spellbook - prompt templates cu variabile
### @health <!-- Se populează automat când propunerile din secțiunile de sus depășesc 30 zile -->
- [ ] 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 ## Legendă (Matrice Eisenhower)
*Se mută aici când completez* | Emoji | Urgent | Important | Ce fac |
|-------|--------|-----------|--------|
| ⚡ | DA | DA | Fă ACUM |
| 📌 | NU | DA | Planifică |
| ⏰ | DA | NU | Fă rapid |
| 💡 | NU | NU | Poate cândva |
--- - RECOMANDAT = am evaluat că merită
- NERECOMANDAT = am evaluat că nu merită acum (motiv)
## ❌ Renunțat - [insights/YYYY-MM-DD.md] = referință la sursa originală
*Se mută aici când nu mai e relevant*
---
*Ultima actualizare: 2026-01-31*

View File

@@ -0,0 +1,52 @@
# Gândul de dimineață - 2026-01-31
**Tags:** @health @coaching #tony-robbins #fiziologie #pattern-interrupt
## Mesaj trimis
[❤️ Echo] **GÂNDUL DE DIMINEAȚĂ** 🌅
> *"Depresia are o postură: umeri căzuți, cap în jos, respirație superficială. Energia are alta: corp deschis, respirație adâncă."*
> — Tony Robbins
Când te simți blocat, nu încerca să-ți schimbi gândurile cu forța.
**Schimbă-ți corpul PRIMUL.**
Cele 3 lucruri care controlează cum te simți:
1. **Fiziologia** — cum stai, cum respiri, cum te miști
2. **Focusul** — ce vezi, ce observi, cum privești
3. **Limbajul** — ce-ți spui, cum numești experiența
Poți să tot încerci să "gândești pozitiv" cu umerii căzuți și respirația superficială. Nu va merge.
Dar ridică-te. Deschide pieptul. Respiră adânc. Și vezi ce se întâmplă cu gândurile.
---
**🎯 PROVOCAREA ZILEI** *(Mișcare de 2 minute)*
Când citești asta, oriunde ai fi:
1. **Ridică-te** (sau schimbă poziția complet)
2. **Fă 5 respirații adânci** — inspiră 4 sec, expiră 6 sec
3. **Întinde-te** — ridică brațele, deschide pieptul
4. **Mergi 2 minute** — oriunde, fără scop
Nu e exercițiu. E **pattern interrupt** — resetare de stare.
Corpul nu știe să mintă. Folosește asta.
---
*O zi cu energie!*
## Surse folosite
- [Tony Robbins - Extraordinary Life](files.html#kb/youtube/2026-01-31_tony-robbins-secret-extraordinary-life.md) - Cele 3 lucruri care controlează emoțiile (fiziologie, focus, limbaj), pattern interrupt, citat despre postură și depresie
- [Insights 2026-01-31](files.html#kb/insights/2026-01-31.md) - Reminder "ridică-te, mergi 2 min" (propunere)
## Provocarea zilei
TIP: Mișcare fizică / Pattern Interrupt
PROVOCARE: Ridică-te, fă 5 respirații adânci (4-6), întinde-te, mergi 2 minute. Resetare de stare prin corp.

View File

@@ -1,5 +1,26 @@
{ {
"notes": [ "notes": [
{
"file": "notes-data/coaching/2026-01-31-dimineata.md",
"title": "Gândul de dimineață - 2026-01-31",
"date": "2026-01-31",
"tags": [
"tony-robbins",
"fiziologie",
"pattern-interrupt"
],
"domains": [
"health"
],
"types": [
"coaching"
],
"category": "coaching",
"project": null,
"subdir": null,
"video": "",
"tldr": "PROVOCARE: Ridică-te, fă 5 respirații adânci (4-6), întinde-te, mergi 2 minute. Resetare de stare prin corp."
},
{ {
"file": "notes-data/insights/2026-01-31.md", "file": "notes-data/insights/2026-01-31.md",
"title": "Insights 2026-01-31", "title": "Insights 2026-01-31",
@@ -20,7 +41,124 @@
"project": null, "project": null,
"subdir": null, "subdir": null,
"video": "", "video": "",
"tldr": "*Scanare completă: 9 note YouTube | 2026-01-31*" "tldr": "*Scanare: 9 note YouTube | 2026-01-31*"
},
{
"file": "notes-data/projects/FLUX-JOBURI.md",
"title": "Flux Complet Joburi Echo",
"date": "2026-01-31",
"tags": [],
"domains": [],
"types": [],
"category": "projects",
"project": null,
"subdir": null,
"video": "",
"tldr": "*Acest document se actualizează când se modifică fluxul joburilor.*"
},
{
"file": "notes-data/projects/grup-sprijin/README.md",
"title": "Grup de Sprijin - Lideri Cercetași",
"date": "2026-01-31",
"tags": [
"grup-sprijin"
],
"domains": [
"sprijin"
],
"types": [],
"category": "projects",
"project": "grup-sprijin",
"subdir": null,
"video": "",
"tldr": ""
},
{
"file": "notes-data/projects/grup-sprijin/biblioteca/exercitiu-de-vorba-cu-emotia.md",
"title": "De vorbă cu... (emoția)",
"date": "2026-01-31",
"tags": [
"daniela-graure",
"emotii",
"acceptare",
"iubire",
"grup-sprijin"
],
"domains": [
"health",
"sprijin"
],
"types": [
"exercitiu"
],
"category": "projects",
"project": "grup-sprijin",
"subdir": "biblioteca",
"video": "",
"tldr": "*Sursă: Daniela Graure*"
},
{
"file": "notes-data/projects/grup-sprijin/biblioteca/intrebare-moment-greu-cadou.md",
"title": "Întrebare: Ce moment greu s-a dovedit cadou?",
"date": "2026-01-31",
"tags": [
"tony-robbins",
"grup-sprijin"
],
"domains": [
"sprijin"
],
"types": [
"intrebare"
],
"category": "projects",
"project": "grup-sprijin",
"subdir": "biblioteca",
"video": "",
"tldr": "*Creat:* 2026-01-31"
},
{
"file": "notes-data/projects/grup-sprijin/biblioteca/fisa-blocare-vs-deblocare.md",
"title": "Fișă: Blocare vs Deblocare",
"date": "2026-01-31",
"tags": [
"fiziologie",
"tony-robbins",
"grup-sprijin"
],
"domains": [
"sprijin"
],
"types": [
"exercitiu",
"fisa"
],
"category": "projects",
"project": "grup-sprijin",
"subdir": "biblioteca",
"video": "",
"tldr": "*Creat:* 2026-01-31"
},
{
"file": "notes-data/projects/grup-sprijin/biblioteca/intrebare-pentru-cine-altcineva.md",
"title": "Întrebare: Pentru cine altcineva faci asta?",
"date": "2026-01-31",
"tags": [
"motivatie",
"sens",
"grup-sprijin"
],
"domains": [
"sprijin"
],
"types": [
"intrebare"
],
"category": "projects",
"project": "grup-sprijin",
"subdir": "biblioteca",
"video": "",
"tldr": "*Creat:* 2026-01-31"
}, },
{ {
"file": "notes-data/youtube/2026-01-31_tony-robbins-secret-extraordinary-life.md", "file": "notes-data/youtube/2026-01-31_tony-robbins-secret-extraordinary-life.md",
@@ -37,13 +175,28 @@
"video": "", "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..." "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": "memory/2026-01-31.md",
"title": "Memory 2026-01-31",
"date": "2026-01-31",
"tags": [],
"domains": [],
"types": [
"memory"
],
"category": "memory",
"project": null,
"subdir": null,
"video": "",
"tldr": "- Insights trebuie să aibă status clar ca să nu se repete propunerile"
},
{ {
"file": "notes-data/projects/vending-master/README.md", "file": "notes-data/projects/vending-master/README.md",
"title": "Proiect: Vending Master - Integrare Website → ROA", "title": "Proiect: Vending Master - Integrare Website → ROA",
"date": "2026-01-30", "date": "2026-01-30",
"tags": [ "tags": [
"vending-master", "integrare",
"integrare" "vending-master"
], ],
"domains": [ "domains": [
"work" "work"
@@ -55,42 +208,6 @@
"video": "", "video": "",
"tldr": "[conversations/2026-01-30-conversatie-completa.md](https://moltbot.tailf7372d.ts.net/echo/files.html#conversations/2026-01-30-conversatie-completa.md)" "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", "file": "notes-data/projects/grup-sprijin/biblioteca/meditatie-mindfulness.md",
"title": "Moment de mindfulness", "title": "Moment de mindfulness",
@@ -112,6 +229,29 @@
"video": "", "video": "",
"tldr": "(De dezvoltat)" "tldr": "(De dezvoltat)"
}, },
{
"file": "notes-data/projects/grup-sprijin/biblioteca/exercitiu-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/meditatie-eu-sunt-mai-mare.md", "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", "title": "Eu sunt mai mare decât gândurile și emoțiile mele",
@@ -155,29 +295,6 @@
"video": "", "video": "",
"tldr": "(De dezvoltat - Marius să adauge textul complet)" "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", "file": "notes-data/projects/grup-sprijin/biblioteca/intrebare-copil-interior.md",
"title": "Ce îți aducea bucurie când erai mic?", "title": "Ce îți aducea bucurie când erai mic?",
@@ -248,7 +365,26 @@
"tldr": "3. Ce ai făcut ASTĂZI care să îți aducă acea emoție?" "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", "file": "notes-data/projects/grup-sprijin/biblioteca/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": "biblioteca",
"video": "",
"tldr": ""
},
{
"file": "notes-data/projects/grup-sprijin/biblioteca/reflectie-beneficiu-grup-siguranta.md",
"title": "Beneficiul grupului - siguranță", "title": "Beneficiul grupului - siguranță",
"date": "2026-01-30", "date": "2026-01-30",
"tags": [ "tags": [
@@ -525,21 +661,21 @@
} }
], ],
"stats": { "stats": {
"total": 26, "total": 33,
"by_domain": { "by_domain": {
"work": 9, "work": 9,
"health": 3, "health": 5,
"growth": 3, "growth": 3,
"sprijin": 12, "sprijin": 16,
"scout": 1 "scout": 1
}, },
"by_category": { "by_category": {
"coaching": 0, "coaching": 1,
"insights": 1, "insights": 1,
"projects": 12, "projects": 17,
"retete": 1, "retete": 1,
"youtube": 9, "youtube": 9,
"memory": 2, "memory": 3,
"conversations": 1 "conversations": 1
} }
}, },

View File

@@ -8,7 +8,8 @@ Idei extrase din note YouTube. Format: `[ ]` neprocesat, `[x]` făcut, `[→]` b
## @work - Productivitate & Automatizări ## @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) - [x] ⚡ Verificare securitate Clawdbot (port, trustedProxies) - FĂCUT 2026-01-31 de Echo Work
- [x] ⚡ Git commit + push restructurare - FĂCUT 2026-01-31 de Echo Work (99 fișiere)
- [ ] 📌 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) - [ ] 📌 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) - [ ] 💡 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) - [ ] 💡 Spellbook - prompt templates cu variabile - [Kitze](https://moltbot.tailf7372d.ts.net/echo/files.html#kb/youtube/2026-01-30_clawdbot-personal-os-kitze.md)
@@ -24,17 +25,18 @@ Idei extrase din note YouTube. Format: `[ ]` neprocesat, `[x]` făcut, `[→]` b
## @growth - Dezvoltare personală ## @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) - [x] ⚡ Exercițiu Priming în morning-coaching - INTEGRAT în job morning-coaching (citește din insights)
- [ ] 📌 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) - [x] 📌 Pattern Interrupt tehnica - INTEGRAT în job morning-coaching ca provocare practică
- [ ] 💡 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) - [ ] 💡 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)
- [x] 💡 "Pentru cine altcineva faci?" - INTEGRAT în coaching dimineață/seară
--- ---
## @sprijin - Grup sprijin ## @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) - [x] ⚡ Fișă "blocare vs deblocare" - CREAT `kb/projects/grup-sprijin/biblioteca/fisa-blocare-vs-deblocare.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) - [x] 📌 Întrebare "Ce moment greu s-a dovedit cadou?" - CREAT `kb/projects/grup-sprijin/biblioteca/intrebare-moment-greu-cadou.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) - [x] 💡 "Pentru cine altcineva faci?" - CREAT `kb/projects/grup-sprijin/biblioteca/intrebare-pentru-cine-altcineva.md`
--- ---
@@ -46,13 +48,19 @@ Idei extrase din note YouTube. Format: `[ ]` neprocesat, `[x]` făcut, `[→]` b
## Legendă ## Legendă
- `[ ]` = neprocesat **Marcare:**
- `[x]` = făcut - `[ ]` = disponibil
- `[x]` = executat
- `[→]` = mutat în backlog - `[→]` = mutat în backlog
- `[—]` = renunțat/skip - `[—]` = skip
- ⚡ = urgent+important
- 📌 = important **Prioritate (Matrice Eisenhower):**
- 💡 = nice-to-have | Emoji | Urgent | Important |
|-------|--------|-----------|
| ⚡ | DA | DA |
| 📌 | NU | DA |
| ⏰ | DA | NU |
| 💡 | NU | NU |
--- ---

262
kb/projects/FLUX-JOBURI.md Normal file
View File

@@ -0,0 +1,262 @@
# Flux Complet Joburi Echo
**Actualizat:** 2026-01-31
**Autor:** Echo Work
---
## 📋 Rezumat Joburi
| Job | Agent | Când (UTC) | Când (București) | Unde trimite |
|-----|-------|------------|------------------|--------------|
| morning-report | echo-work | 06:30 | 08:30 | Discord #echo-work |
| morning-coaching | echo-health | 07:00 | 09:00 | WhatsApp principal |
| respiratie-09 | echo-health | 07:00 | 09:00 | Discord #echo-health |
| respiratie-10 | echo-health | 08:00 | 10:00 | Discord #echo-health |
| respiratie-11 | echo-health | 09:00 | 11:00 | Discord #echo-health |
| respiratie-12 | echo-health | 10:00 | 12:00 | Discord #echo-health |
| respiratie-13 | echo-health | 11:00 | 13:00 | Discord #echo-health |
| respiratie-14 | echo-health | 12:00 | 14:00 | Discord #echo-health |
| respiratie-15 | echo-health | 13:00 | 15:00 | Discord #echo-health |
| respiratie-16 | echo-health | 14:00 | 16:00 | Discord #echo-health |
| respiratie-17 | echo-health | 15:00 | 17:00 | Discord #echo-health |
| respiratie-18 | echo-health | 16:00 | 18:00 | Discord #echo-health |
| respiratie-19 | echo-health | 17:00 | 19:00 | Discord #echo-health |
| evening-report | echo-work | 18:00 | 20:00 | Discord #echo-work |
| evening-coaching | echo-health | 19:00 | 21:00 | WhatsApp principal |
| archive-tasks | main | 03:00 | 05:00 | - (intern) |
| weekly-planning-sun | main | 19:00 duminică | 21:00 | Discord #echo-work |
| project-checkin-tue | main | 15:00 marți | 17:00 | Discord #echo-work |
| project-checkin-thu | main | 15:00 joi | 17:00 | Discord #echo-work |
| grup-sprijin-pregatire | main | 15:00 3 feb | 17:00 | WhatsApp |
| grup-sprijin-5feb | main | 15:00 5 feb | 17:00 | WhatsApp |
---
## 🔄 Fluxul Complet
```
┌─────────────────────────────────────────────────────────────────────┐
│ SURSE PRIMARE │
├─────────────────────────────────────────────────────────────────────┤
│ YouTube video │
│ │ │
│ ▼ (manual - când primești link) │
│ kb/youtube/YYYY-MM-DD_titlu.md │
│ │ │
│ │ (rapoarte scanează note noi) │
│ ▼ │
│ kb/insights/YYYY-MM-DD.md │
│ │ │
│ ├──────────────────┬──────────────────┐ │
│ ▼ ▼ ▼ │
│ RAPOARTE COACHING FIȘE/NOTE │
│ (propun) (se inspiră) (se creează) │
└─────────────────────────────────────────────────────────────────────┘
```
---
## 📝 Cine Creează Ce
### 1. Note YouTube (`kb/youtube/`)
| Când | Cine | Ce face |
|------|------|---------|
| Manual | Orice agent | Când primește link YouTube → extrage transcript → salvează notă |
**Format:** `kb/youtube/YYYY-MM-DD_titlu-slug.md`
**Conține:**
- TL;DR
- Puncte cheie
- Citate relevante
- Exerciții practice
- Tags: #autor, @domeniu
---
### 2. Insights (`kb/insights/`)
| Când | Cine | Ce face |
|------|------|---------|
| morning-report | echo-work | Scanează `kb/youtube/` ultimele 48h → extrage idei noi → adaugă în insights |
| evening-report | echo-work | Scanează `kb/youtube/` ultimele 48h → extrage idei noi → adaugă în insights |
**Format:** `kb/insights/YYYY-MM-DD.md`
**Structură:**
```markdown
## @work - Productivitate
- [ ] ⚡ Propunere urgentă - [link notă]
- [ ] 📌 Propunere importantă - [link notă]
## @health - Sănătate
- [ ] 💡 Propunere nice-to-have - [link notă]
```
**Sistem marcare:**
- `[ ]` = disponibil (rapoarte pot propune)
- `[x]` = implementat (nu mai propune)
- `[→]` = mutat în backlog
- `[—]` = skip/nu vreau
---
### 3. Coaching Notes (`kb/coaching/`)
| Când | Cine | Ce face |
|------|------|---------|
| morning-coaching | echo-health | Salvează mesajul trimis + referințe la surse |
| evening-coaching | echo-health | Salvează mesajul trimis + referințe la surse |
**Format:** `kb/coaching/YYYY-MM-DD-dimineata.md` sau `YYYY-MM-DD-seara.md`
**Conține:**
```markdown
# Gândul de dimineață - 2026-01-31
## Mesaj trimis
[conținut]
## Surse folosite
- [Titlu Notă](files.html#kb/youtube/YYYY-MM-DD_titlu.md) - ce am extras
- [Insights YYYY-MM-DD](files.html#kb/insights/YYYY-MM-DD.md) - ce propunere am folosit
## Provocarea zilei
TIP: fiziologie
PROVOCARE: descriere
```
---
### 4. Fișe Grup Sprijin (`kb/projects/grup-sprijin/biblioteca/`)
| Când | Cine | Ce face |
|------|------|---------|
| După aprobare | echo-work | Creează fișă când Marius aprobă din raport |
| Manual | Orice agent | Când Marius cere |
**Format:** `fisa-titlu.md`, `intrebare-titlu.md`, `meditatie-titlu.md`
---
## 📊 Cine Citește De Unde
### morning-report / evening-report (echo-work)
**CITEȘTE:**
- `kb/youtube/` - note noi (ultimele 48h) pentru a extrage în insights
- `kb/insights/` - propuneri `[ ]` (ultimele 7 zile)
- `kb/backlog.md` - 1-2 propuneri (rotație) + verifică > 30 zile
**CREEAZĂ:**
- Adaugă în `kb/insights/` idei din note noi
- Creează fișe/note când Marius aprobă
**MARCHEAZĂ în insights:**
- `[x]` + data când Marius zice "ok" și se execută
- `[→]` + adaugă în backlog când Marius zice "backlog"
- `[—]` când Marius zice "nu/skip"
- `[→]` + adaugă în backlog "De revizuit" când Marius ignoră
**ACTUALIZEAZĂ backlog:**
- Adaugă cu nivel (⚡/📌/💡) + RECOMANDAT/NERECOMANDAT + referință
- Șterge când se execută sau se renunță
- Propune curățare pentru > 30 zile
---
### morning-coaching / evening-coaching (echo-health)
**CITEȘTE:**
- `kb/coaching/` - **ultimele 7 zile** (NU repeta teme!)
- `kb/youtube/` - note pentru citate/idei
- `kb/insights/` - propuneri pentru exerciții practice
- `kb/projects/grup-sprijin/biblioteca/` - fișe și exerciții
- `memory/provocare-azi.md` - pentru follow-up seară
**CREEAZĂ:**
- `kb/coaching/YYYY-MM-DD-dimineata.md` sau `-seara.md` (cu referințe la surse!)
- `memory/provocare-azi.md` - provocarea zilei
**MARCHEAZĂ:**
- NIMIC în insights (doar se inspiră, nu marchează)
---
### respiratie-* (echo-health)
**CITEȘTE:** Nimic
**CREEAZĂ:** Nimic (doar trimite mesaj scurt)
**MARCHEAZĂ:** Nimic
---
## ⚠️ Evitarea Repetărilor
### Rapoarte (echo-work)
- Propun doar din `[ ]` (ignoră `[x]`, `[→]`, `[—]`)
- Marchează după răspunsul lui Marius
### Coaching (echo-health)
- Verifică `kb/coaching/` ultimele 14 zile
- NU repetă aceleași teme/citate/exerciții
- Salvează cu referințe pentru tracking
---
## 🔍 Verificări și Posibile Probleme
### ✅ OK
- Rapoarte extrag din note → insights ✓
- Marius aprobă → se marchează ✓
- Coaching se inspiră fără a marca → ✓
- Coaching salvează cu referințe → ✓
### ⚠️ De monitorizat
- **Curățare insights vechi:** Insights mai vechi de 30 zile cu `[ ]` - ce facem?
- Propunere: La fiecare raport, dacă propunerea e > 14 zile nemarcată → marcăm `[—]` automat
- **Sincronizare între agenți:** insights e în folder partajat, mai mulți agenți scriu
- Propunere: OK așa, fiecare agent adaugă cu sursa lui
- **Note YouTube fără insights:** Note vechi care n-au fost procesate
- Propunere: Rapoarte verifică ultimele 48h, restul rămâne ca referință
---
## 📅 Ordine Cronologică Zilnică (București)
| Ora | Job | Agent | Ce face |
|-----|-----|-------|---------|
| 05:00 | archive-tasks | main | Arhivează task-uri vechi |
| 08:30 | morning-report | echo-work | Raport + propuneri din insights |
| 09:00 | morning-coaching | echo-health | Mesaj dimineață WhatsApp |
| 09:00-19:00 | respiratie-* | echo-health | Reminder-uri orare |
| 20:00 | evening-report | echo-work | Raport + propuneri din insights |
| 21:00 | evening-coaching | echo-health | Mesaj seară WhatsApp |
---
## 📁 Structura Fișiere
```
kb/
├── youtube/ # Note din video-uri
│ └── YYYY-MM-DD_titlu.md
├── insights/ # Propuneri extrase
│ └── YYYY-MM-DD.md
├── coaching/ # Mesaje coaching salvate
│ ├── YYYY-MM-DD-dimineata.md
│ └── YYYY-MM-DD-seara.md
├── backlog.md # Propuneri amânate
└── projects/
└── grup-sprijin/
├── biblioteca/ # Fișe și exerciții
└── fise/ # Fișe pentru întâlniri
```
---
*Acest document se actualizează când se modifică fluxul joburilor.*

View File

@@ -2,14 +2,33 @@
"description": "Proiect grup de sprijin - lideri cercetași", "description": "Proiect grup de sprijin - lideri cercetași",
"defaultDomains": ["sprijin"], "defaultDomains": ["sprijin"],
"defaultTags": ["grup-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, "inferTypeFromFilename": true,
"filenameTypeMap": { "filenameTypeMap": {
"meditatie": "meditatie", "exercitiu-": "exercitiu",
"exercitiu": "exercitiu", "meditatie-": "meditatie",
"intrebare": "intrebare", "intrebare-": "intrebare",
"reflectie": "reflectie", "reflectie-": "reflectie",
"fisa": "fisa" "fisa-": "fisa"
} },
"biblioteca": {
"location": "biblioteca/",
"description": "Toate resursele (exerciții, meditații, întrebări, fișe) se pun aici",
"prefixRequired": true,
"validPrefixes": {
"exercitiu-": "Exerciții practice (perechi, grup)",
"meditatie-": "Meditații ghidate",
"intrebare-": "Întrebări de reflecție/introspecție",
"reflectie-": "Teme de reflecție, concepte",
"fisa-": "Fișe complete de întâlnire (cu dată: fisa-YYYY-MM-DD-tema.md)"
},
"filenameFormat": "{prefix}{slug}.md",
"examples": [
"exercitiu-de-vorba-cu-emotia.md",
"meditatie-demnitate.md",
"intrebare-copil-interior.md",
"reflectie-oglinda.md",
"fisa-2026-02-05-ancorare-oglinda.md"
]
},
"templateFisa": "template-fisa.md"
} }

View File

@@ -13,6 +13,20 @@
- Tehnici NLP - Tehnici NLP
- Întrebări puternice - Întrebări puternice
## Structura fișierelor
**Tot în `biblioteca/`** cu prefix obligatoriu:
| Prefix | Descriere | Exemplu |
|--------|-----------|---------|
| `exercitiu-` | Exerciții practice | `exercitiu-de-vorba-cu-emotia.md` |
| `meditatie-` | Meditații ghidate | `meditatie-demnitate.md` |
| `intrebare-` | Întrebări de reflecție | `intrebare-copil-interior.md` |
| `reflectie-` | Teme/concepte | `reflectie-oglinda.md` |
| `fisa-` | Fișe de întâlnire | `fisa-2026-02-05-tema.md` |
Vezi `.rules.json` pentru detalii.
## Întâlniri ## Întâlniri
- [x] Prima întâlnire (ianuarie 2026) - [x] Prima întâlnire (ianuarie 2026)
- [ ] **Joi 5 februarie 2026, 18:00** - următoarea - [ ] **Joi 5 februarie 2026, 18:00** - următoarea

View File

@@ -0,0 +1,87 @@
# De vorbă cu... (emoția)
**Tags:** @health @exercitiu #daniela-graure #emotii #acceptare #iubire
**Autor:** Daniela Graure
**Durată:** 10-15 min
**Participanți:** perechi de 2
---
## Descriere
Exercițiu de dialog cu o emoție pentru a o recunoaște, accepta și elibera prin iubire.
## Instrucțiuni
1. Se fac **perechi de câte doi** parteneri.
2. Primul partener alege o **emoție vie, actuală de nivel 3-5** (nu copleșitoare).
3. Al doilea partener citește textul și înlocuiește `[.....]` cu numele emoției. Face pauză pentru ca primul partener să repete.
4. Primul partener **închide ochii** și repetă cuvintele și le simte.
5. Ton calm, lent. Pauze suficiente între secțiuni.
6. După exercițiu: moment de liniște, apoi sharing opțional.
---
## Textul exercițiului
*(Al doilea partener citește, primul repetă cu ochii închiși)*
### Partea 1: Eu sunt mai mare
> Eu sunt mai mare
> Eu sunt o ființă întreagă și completă
> Eu sunt mai mare decât corpul meu
> Eu sunt mai mare decât gândurile și emoțiile care mă traversează
---
### Partea 2: Tu ești o imagine
> Tu, `[.....]`, ești o emoție care mă traversezi acum
> Tu, `[.....]`, ești o imagine în mintea mea
> Tu, `[.....]`, ești o rezistență în mintea mea
---
### Partea 3: Bine ai venit
> Bine ai venit, `[.....]`
> Te primesc
> Mulțumesc, `[.....]`
> Mulțumesc pentru mesajul tău
> Ești un mesager minunat
---
### Partea 4: Te văd
> Mulțumesc, `[.....]`, că te văd
> Mulțumesc că ai ieșit din subconștient
> Mulțumesc mie că te-am creat
> Te binecuvântez, `[.....]`, exact așa cum ești tu în acest moment
> Mulțumesc pentru mesajul tău
---
### Partea 5: Te iubesc și te eliberez
> Te iubesc, `[.....]`
> Te iubesc și dacă pleci, și te iubesc și dacă mai rămâi
> Pur și simplu te iubesc
> Nu vreau să te țin ca într-o colivie
> E dreptul tău divin să te întorci în iubirea din care ai fost creată
> Te iubesc, `[.....]`
> Te iubesc și decid să te eliberez
---
### Partea 6: Eliberare (ghidare)
*Al doilea partener spune:*
> Și în acest moment, trimiți către `[.....]` toată iubirea de care ești capabil(ă) în acest moment.
> O învălui în iubire și observi cum ea se transformă, cum se topește în iubire.
---
*Sursă: Daniela Graure*

View File

@@ -0,0 +1,46 @@
# Fișă: Blocare vs Deblocare
**Tags:** @sprijin @exercitiu #fiziologie #tony-robbins
## Scop
Să înțelegem cum starea fizică influențează starea emoțională și să practicăm tehnici de deblocare.
## Concept cheie
> "Motion creates emotion" - Tony Robbins
Când suntem blocați emoțional, corpul reflectă asta: umeri căzuți, respirație superficială, privire în jos. Schimbând fiziologia, schimbăm și starea.
## Exercițiu practic (15 min)
### Partea 1: Recunoașterea blocării (5 min)
1. Gândește-te la un moment recent când te-ai simțit blocat
2. Observă ce se întâmplă în corp când te gândești la asta:
- Cum e respirația?
- Cum stau umerii?
- Unde e privirea?
- Ce tensiune simți?
### Partea 2: Pattern Interrupt (5 min)
1. **Fiziologie:** Ridică-te, schimbă poziția, sari pe loc 30 secunde
2. **Respirație:** 3 respirații adânci (4 sec inspir, 7 sec expir)
3. **Focus:** Privește în sus, zâmbește (chiar forțat!)
4. **Mișcare:** Fă 10 genoflexiuni sau mergi alert 1 minut
### Partea 3: Reflecție (5 min)
- Ce s-a schimbat în corp?
- Ce s-a schimbat în minte?
- Ce poți face data viitoare când te simți blocat?
## Întrebări pentru discuție
- Când te simți blocat, ce e primul lucru care se schimbă la tine? (corp, gânduri, emoții)
- Ai observat pattern-uri? (ore din zi, situații, persoane)
- Ce tehnici ai încercat până acum? Ce a funcționat?
## De reținut
- Blocarea nu e o stare permanentă - e un moment
- Corpul e poarta cea mai rapidă de deblocare
- 30 secunde de mișcare pot schimba totul
---
*Sursa:* Tony Robbins - The Secret to an Extraordinary Life
*Creat:* 2026-01-31

View File

@@ -0,0 +1,29 @@
# Întrebare: Ce moment greu s-a dovedit cadou?
**Tags:** @sprijin @intrebare #reflectie #tony-robbins
## Context
În retrospectivă, multe momente dificile se dovedesc a fi puncte de cotitură pozitive. Această întrebare ajută la reframarea experiențelor grele.
## Întrebarea
> **"Gândește-te la un moment din viața ta care părea greu, dar care s-a dovedit a fi un cadou. Ce ai învățat din el?"**
## Variante
- "Ce criză din trecut ți-a schimbat viața în bine?"
- "Ce situație ai evita dacă ai putea, dar de fapt te-a format?"
- "Ce eșec s-a transformat în lecție valoroasă?"
## Cum să folosești în grup
1. Dă timp de gândire (2-3 min în liniște)
2. Împărtășire voluntară - nimeni nu e obligat
3. Ascultare fără sfaturi - doar prezență
4. Opțional: Ce pattern observi la povești? (reziliență, adaptare, creștere)
## De ce funcționează
- Schimbă perspectiva de la "victimă" la "învățăcel"
- Arată că suntem mai puternici decât credem
- Creează speranță pentru momentele grele actuale
---
*Sursa:* Tony Robbins - The Secret to an Extraordinary Life
*Creat:* 2026-01-31

View File

@@ -0,0 +1,36 @@
# Întrebare: Pentru cine altcineva faci asta?
**Tags:** @sprijin @intrebare #motivatie #sens
## Context
Când facem ceva doar pentru noi, uneori ne oprim. Când facem pentru alții, găsim resurse pe care nu știam că le avem.
## Întrebarea
> **"Pentru cine altcineva faci asta, în afară de tine?"**
## Când să folosești
- Când cineva e blocat într-o decizie grea
- Când lipsa motivației e o problemă
- Când cineva vrea să renunțe la ceva important
- La provocări de sănătate (post, exercițiu, schimbare obiceiuri)
## Variante
- "Cine ar beneficia dacă tu ai reuși?"
- "Cine te urmărește și ar învăța din exemplul tău?"
- "Pentru cine vrei să fii mai bun?"
- "Cui îi arăți că se poate?"
## Cum să folosești în grup
1. Pune întrebarea în context specific
2. Lasă tăcere - răspunsul vine din adânc
3. Urmărește: "Ce simți când te gândești la persoana aia?"
4. Opțional: "Cum s-ar schimba abordarea dacă te-ai gândi la ei?"
## De ce funcționează
- Activează motivația extrinsecă (pentru alții) care e adesea mai puternică
- Ne conectează la sens și scop mai mare
- Iese din "ego" în "serviciu"
---
*Sursa:* Inspirat din coaching și note post apă
*Creat:* 2026-01-31

View File

@@ -22,9 +22,54 @@
- Secțiuni: Urgent+Important, Important, Nice-to-have, Făcut, Renunțat - Secțiuni: Urgent+Important, Important, Nice-to-have, Făcut, Renunțat
- Același format checkbox ca insights - Același format checkbox ca insights
### Protocol cross-agent (AGENTS.md + SOUL-base.md)
- Când primesc mesaj de la alt agent → confirm PE CANAL
- Format: "Am primit de la [agent]: [rezumat]" → fac → "Done ✅"
- Marius nu vede mesajele interne - trebuie transparență
### Link-uri markdown standard
- NU custom parser, CI format standard: `[Titlu](files.html#kb/path.md)`
- Convertit fișierele existente la format corect
- Actualizat SOUL-base.md cu instrucțiuni
### Dashboard Activity - surse multiple
- Cron jobs executate (mov)
- Git commits (portocaliu)
- Fișiere create/modificate în kb/ (teal)
- Task-uri din tasks.json (verde)
- API endpoint nou: /api/activity
### Dashboard alte îmbunătățiri
- Modal: background solid (era transparent)
- Owner: adăugat Robert 👷 (angajat nou)
- Statistici: label-uri clare (Tasks azi/săpt./lună)
- Cron jobs: ora București în loc de UTC
### Files view modes (Windows Explorer style)
- **List**: grilă multi-coloană, icon mic + nume
- **Details**: tabel cu coloane (Nume, Tip, Mărime, Dată) + sortare
- **Tiles**: grid cu iconuri mari (ca înainte)
- Sortare ASC/DESC după nume sau dată
- Setări salvate în localStorage
### USER.md - Reguli propuneri
- 80/20 STRICT: impact mare, efort mic
- NU complica fluxul
- Recomandare explicită: ✅/⚠️/❌ + de ce
- Arată TOATE propunerile, nu doar recomandate
## De făcut ## De făcut
- Verificare că rapoartele funcționează corect la 08:30 și 20:00 - [ ] **MONITORIZARE JOBURI** (cerut de Marius):
- **AZI 20:00** → evening-report (echo-work) → Discord #echo-work
- **AZI 21:00** → evening-coaching (echo-health) → Discord #echo-health + fișier kb/coaching/
- **MÂINE 08:30** → morning-report (echo-work) → Discord #echo-work
- **MÂINE 09:00** → morning-coaching (echo-health) → Discord #echo-health + fișier kb/coaching/
- Verifică: mesaj trimis + fișier creat
- Confirmă lui Marius după fiecare
## Învățat ## Învățat
- Marius preferă totul într-un singur loc (scanare în raport, nu job separat) - 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 - Insights trebuie să aibă status clar ca să nu se repete propunerile
- Link-uri: format markdown standard, nu parsere custom
- Dashboard: multiple surse de date pentru Activity
- Files: view modes ca Windows Explorer (List/Details/Tiles)