Update dashboard, memory, root (+40 ~22 -2)

This commit is contained in:
Echo
2026-02-12 10:15:21 +00:00
parent 3ffd9332e9
commit e5d098305d
64 changed files with 9623 additions and 696 deletions

View File

@@ -2048,12 +2048,6 @@ def process_youtube(url):
sys.executable, str(TOOLS_DIR / 'update_notes_index.py')
], capture_output=True)
# Add task to kanban
subprocess.run([
sys.executable, str(KANBAN_DIR / 'update_task.py'),
'add', 'in-progress', f'Sumarizare: {title[:30]}...', url, 'medium'
], capture_output=True)
print(f"Created note: {filename}")
return filename

View File

@@ -52,6 +52,13 @@
"description": "",
"created": "2026-02-03T21:02:31Z",
"priority": "medium"
},
{
"id": "task-041",
"title": "Raport dimineață trimis pe email",
"description": "",
"created": "2026-02-04T06:31:05Z",
"priority": "medium"
}
]
}

View File

@@ -1,5 +1,5 @@
{
"lastUpdated": "2026-02-11T16:14:09.539711",
"lastUpdated": "2026-02-11T22:07:48.431522",
"habits": [
{
"id": "95c15eef-3a14-4985-a61e-0b64b72851b0",
@@ -15,14 +15,19 @@
"count": 5
},
"streak": {
"current": 0,
"current": 1,
"best": 1,
"lastCheckIn": "2026-02-11"
},
"lives": 0,
"completions": [],
"completions": [
{
"date": "2026-02-11",
"type": "check"
}
],
"createdAt": "2026-02-11T00:54:03.447063",
"updatedAt": "2026-02-11T16:14:06.084264"
"updatedAt": "2026-02-11T22:07:24.169781"
},
{
"id": "ceddaa7e-caf9-4038-94bb-da486c586bf8",
@@ -50,7 +55,7 @@
}
],
"createdAt": "2026-02-11T01:58:44.779904",
"updatedAt": "2026-02-11T16:14:09.539711"
"updatedAt": "2026-02-11T22:07:48.431522"
}
]
}

View File

@@ -688,7 +688,7 @@
}
.issue-checkbox.in-progress {
background: rgba(59, 130, 246, 0.3);
background: rgba(59, 130, 246, 0.5);
border-color: #3b82f6;
}
@@ -1071,6 +1071,10 @@
<i data-lucide="file-text"></i>
<span>KB</span>
</a>
<a href="/echo/habits.html" class="nav-item">
<i data-lucide="dumbbell"></i>
<span>Habits</span>
</a>
<a href="/echo/files.html" class="nav-item">
<i data-lucide="folder"></i>
<span>Files</span>
@@ -1448,7 +1452,7 @@
let issuesData = null;
let activityData = [];
let currentFilter = 'all';
let collapsedPriorities = new Set(['backlog']);
let collapsedPriorities = new Set(['backlog', 'done']);
// Priority labels
const priorityLabels = {
@@ -2171,39 +2175,40 @@
filtered = filtered.filter(i => i.owner === currentFilter);
}
// Group by priority
// Separate done from active
const activeIssues = filtered.filter(i => i.status !== 'done');
const doneIssues = filtered.filter(i => i.status === 'done');
// Group active by priority
const grouped = {};
priorityOrder.forEach(p => grouped[p] = []);
filtered.forEach(issue => {
activeIssues.forEach(issue => {
const p = issue.priority || 'backlog';
if (grouped[p]) grouped[p].push(issue);
else grouped['backlog'].push(issue);
});
// Sort each group: todo first, then by date
// Sort each group by date (newest first)
Object.keys(grouped).forEach(p => {
grouped[p].sort((a, b) => {
if (a.status === 'done' && b.status !== 'done') return 1;
if (a.status !== 'done' && b.status === 'done') return -1;
return new Date(b.created) - new Date(a.created);
});
grouped[p].sort((a, b) => new Date(b.created) - new Date(a.created));
});
let html = '';
// Render active issues by priority
priorityOrder.forEach(priority => {
const issues = grouped[priority];
if (issues.length === 0) return;
const isCollapsed = collapsedPriorities.has(priority);
const todoCount = issues.filter(i => i.status !== 'done').length;
html += `
<div class="priority-group">
<div class="priority-header ${isCollapsed ? 'collapsed' : ''}" onclick="togglePriority('${priority}')">
<i data-lucide="chevron-down"></i>
<span>${priorityLabels[priority]}</span>
<span style="margin-left: auto; opacity: 0.7">${todoCount}/${issues.length}</span>
<span style="margin-left: auto; opacity: 0.7">${issues.length}</span>
</div>
<div class="priority-content ${isCollapsed ? 'hidden' : ''}">
${issues.map(issue => renderIssueItem(issue)).join('')}
@@ -2212,6 +2217,25 @@
`;
});
// Render done issues separately at the end
if (doneIssues.length > 0) {
const isDoneCollapsed = collapsedPriorities.has('done');
doneIssues.sort((a, b) => new Date(b.completed || b.updated) - new Date(a.completed || a.updated));
html += `
<div class="priority-group">
<div class="priority-header ${isDoneCollapsed ? 'collapsed' : ''}" onclick="togglePriority('done')">
<i data-lucide="chevron-down"></i>
<span>✅ Executate</span>
<span style="margin-left: auto; opacity: 0.7">${doneIssues.length}</span>
</div>
<div class="priority-content ${isDoneCollapsed ? 'hidden' : ''}">
${doneIssues.map(issue => renderIssueItem(issue)).join('')}
</div>
</div>
`;
}
body.innerHTML = html;
lucide.createIcons();
}

View File

@@ -1,5 +1,5 @@
{
"lastUpdated": "2026-02-05T21:53:55.397Z",
"lastUpdated": "2026-02-12T10:05:31.985Z",
"programs": [
"ROACONT",
"ROAGEST",
@@ -39,6 +39,18 @@
"deadline": "2026-02-06",
"updated": "2026-02-02T22:26:59.690Z",
"completed": "2026-02-05T21:53:55.392Z"
},
{
"id": "ROA-003",
"title": "Auto-copiere manoperă din devize stimative în devize reale",
"description": "",
"program": "ROAGEST",
"owner": "marius",
"priority": "backlog",
"status": "todo",
"created": "2026-02-12T10:03:13.378157+00:00",
"deadline": null,
"updated": "2026-02-12T10:05:31.980Z"
}
]
}

View File

@@ -10,19 +10,10 @@
"time": "30 Jan 2026, 22:00"
},
"anaf": {
"ok": false,
"status": "MODIFICĂRI",
"message": "1 modificări detectate",
"lastCheck": "11 Feb 2026, 16:23",
"changesCount": 1,
"changes": [
{
"name": "Declarația 300 - Decont TVA",
"url": "https://static.anaf.ro/static/10/Anaf/Declaratii_R/300.html",
"summary": [
"Pagina s-a modificat (vezi diff)"
]
}
]
"ok": true,
"status": "OK",
"message": "Nicio modificare detectată",
"lastCheck": "12 Feb 2026, 08:00",
"changesCount": 0
}
}

View File

@@ -1,43 +0,0 @@
{
"lastUpdated": "2026-02-11T03:00:04.800665",
"columns": [
{
"id": "backlog",
"name": "Backlog",
"tasks": [
{
"id": "task-006",
"title": "Email digest dimineața",
"description": "Sumar email-uri importante la 8 AM",
"created": "2025-01-30",
"priority": "medium"
},
{
"id": "task-007",
"title": "Calendar sync",
"description": "Alertă înainte de întâlniri Google Calendar",
"created": "2025-01-30",
"priority": "low"
}
]
},
{
"id": "in-progress",
"name": "In Progress",
"tasks": []
},
{
"id": "done",
"name": "Done",
"tasks": [
{
"id": "task-041",
"title": "Raport dimineață trimis pe email",
"description": "",
"created": "2026-02-04T06:31:05Z",
"priority": "medium"
}
]
}
]
}

View File

@@ -1,6 +1,19 @@
{
"lastUpdated": "2026-02-11T16:39:39.457Z",
"lastUpdated": "2026-02-12T07:00:00.000Z",
"items": [
{
"id": "prov-2026-02-12",
"text": "Provocare: Primul Pas Minim (PPM) - alege idee și execută în MAX 10 min",
"context": "Regula PPM: Orice idee pe care o ai astăzi → identifică primul pas care: (1) Durează MAX 10 minute (2) NU necesită alte persoane (3) E CONCRET (nu 'mă gândesc', ci 'scriu', 'sun', 'trimit', 'creez'). La prima pauză (10:00-11:00): Alege UNA din ideile tale recente, identifică PPM-ul, execută-l chiar dacă nu e perfect. La 17:00 notează: Ce idee? Care PPM? L-am executat? Dacă DA: cum mă simt, următorul pas? Dacă NU: ce m-a oprit, ce PPM MAI MIC mâine?",
"example": "Exemplu concret: Ideea 'ar trebui să am task brief template pentru angajat'. PPM greu: 'Creez template complet cu toate secțiunile, testez, ajustez...' PPM SIMPLU: 'Deschid fișier task-brief-template.md și scriu primele 3 secțiuni (Task, Input, Output) în 10 minute'. Sau ideea 'trebuie să documentez soluții probleme clienți'. PPM: 'Creez folder memory/kb/roa/probleme-frecvente/ și scriu PRIMA problemă rezolvată recent în 10 minute'. Cel mai greu pas e PRIMUL - după ce ai început, creierul intră în flow mode.",
"domain": "self",
"dueDate": "2026-02-12",
"done": false,
"doneAt": null,
"source": "Multi-Agent Pattern + Living Files Theory + Context Engineering",
"sourceUrl": "https://moltbot.tailf7372d.ts.net/echo/files.html#memory/kb/coaching/2026-02-12-dimineata.md",
"createdAt": "2026-02-12T07:00:00.000Z"
},
{
"id": "prov-2026-02-11",
"text": "Provocare: Identifică un task pe care îl execuți singur și ar putea fi orchestrat",

View File

@@ -1,120 +0,0 @@
#!/usr/bin/env python3
"""
Helper script for Echo to update kanban tasks.
Usage: python3 update_task.py <action> <args>
Actions:
add <column> <title> [description] [priority]
move <task_id> <to_column>
done <task_id>
list
"""
import json
import sys
from datetime import datetime
from pathlib import Path
TASKS_FILE = Path(__file__).parent / 'tasks.json'
def load_tasks():
with open(TASKS_FILE, 'r') as f:
return json.load(f)
def save_tasks(data):
data['lastUpdated'] = datetime.utcnow().isoformat() + 'Z'
with open(TASKS_FILE, 'w') as f:
json.dump(data, f, indent=2, ensure_ascii=False)
def get_next_id(data):
max_id = 0
for col in data['columns']:
for task in col['tasks']:
num = int(task['id'].split('-')[1])
if num > max_id:
max_id = num
return f"task-{max_id + 1:03d}"
def add_task(column_id, title, description="", priority="medium"):
data = load_tasks()
new_task = {
"id": get_next_id(data),
"title": title,
"description": description,
"created": datetime.utcnow().strftime("%Y-%m-%dT%H:%M:%SZ"),
"priority": priority
}
for col in data['columns']:
if col['id'] == column_id:
col['tasks'].append(new_task)
save_tasks(data)
print(f"Added: {new_task['id']} - {title}")
return
print(f"Column not found: {column_id}")
def move_task(task_id, to_column):
data = load_tasks()
task = None
# Find and remove task
for col in data['columns']:
for t in col['tasks']:
if t['id'] == task_id:
task = t
col['tasks'].remove(t)
break
if task:
break
if not task:
print(f"Task not found: {task_id}")
return
# Add to new column
if to_column == 'done':
task['completed'] = datetime.utcnow().strftime("%Y-%m-%dT%H:%M:%SZ")
for col in data['columns']:
if col['id'] == to_column:
col['tasks'].append(task)
save_tasks(data)
print(f"Moved: {task_id} -> {to_column}")
return
print(f"Column not found: {to_column}")
def done_task(task_id):
move_task(task_id, 'done')
def list_tasks():
data = load_tasks()
for col in data['columns']:
print(f"\n{col['name']} ({len(col['tasks'])})")
print("-" * 40)
for task in col['tasks']:
print(f" [{task['id']}] {task['title']}")
if __name__ == '__main__':
if len(sys.argv) < 2:
print(__doc__)
sys.exit(1)
action = sys.argv[1]
if action == 'add' and len(sys.argv) >= 4:
add_task(
sys.argv[2], # column
sys.argv[3], # title
sys.argv[4] if len(sys.argv) > 4 else "",
sys.argv[5] if len(sys.argv) > 5 else "medium"
)
elif action == 'move' and len(sys.argv) >= 4:
move_task(sys.argv[2], sys.argv[3])
elif action == 'done' and len(sys.argv) >= 3:
done_task(sys.argv[2])
elif action == 'list':
list_tasks()
else:
print(__doc__)