@cccarv82/freya 3.4.1 → 3.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/cli/web-ui.js CHANGED
@@ -28,6 +28,18 @@
28
28
  document.documentElement.setAttribute('data-theme', 'dark');
29
29
  }
30
30
 
31
+ function toggleTheme() {
32
+ var isDark = document.documentElement.getAttribute('data-theme') === 'dark';
33
+ if (isDark) {
34
+ document.documentElement.removeAttribute('data-theme');
35
+ try { localStorage.setItem('freya-theme', 'light'); } catch(_) {}
36
+ } else {
37
+ document.documentElement.setAttribute('data-theme', 'dark');
38
+ try { localStorage.setItem('freya-theme', 'dark'); } catch(_) {}
39
+ }
40
+ }
41
+ window.toggleTheme = toggleTheme;
42
+
31
43
  function setPill(kind, text) {
32
44
  const dot = $('dot');
33
45
  const rail = $('railStatus');
@@ -1407,6 +1419,16 @@
1407
1419
  }
1408
1420
  }
1409
1421
 
1422
+ /* ── Smooth Page Navigation with Transition ── */
1423
+ function navigateTo(url) {
1424
+ document.body.classList.add('navigating');
1425
+ // Close mobile menu if open
1426
+ closeMobileNav();
1427
+ setTimeout(function() {
1428
+ window.location.href = url;
1429
+ }, 180);
1430
+ }
1431
+
1410
1432
  function wireRailNav() {
1411
1433
  const dash = $('railDashboard');
1412
1434
  const rep = $('railReports');
@@ -1423,7 +1445,7 @@
1423
1445
  if (dash) {
1424
1446
  dash.onclick = () => {
1425
1447
  if (!isDashboard) {
1426
- window.location.href = '/';
1448
+ navigateTo('/');
1427
1449
  } else {
1428
1450
  const c = document.querySelector('.centerBody');
1429
1451
  if (c) c.scrollTo({ top: 0, behavior: 'smooth' });
@@ -1432,37 +1454,37 @@
1432
1454
  }
1433
1455
  if (rep) {
1434
1456
  rep.onclick = () => {
1435
- if (curPage !== 'reports') window.location.href = '/reports';
1457
+ if (curPage !== 'reports') navigateTo('/reports');
1436
1458
  };
1437
1459
  }
1438
1460
  if (proj) {
1439
1461
  proj.onclick = () => {
1440
- if (curPage !== 'projects') window.location.href = '/projects';
1462
+ if (curPage !== 'projects') navigateTo('/projects');
1441
1463
  };
1442
1464
  }
1443
1465
  if (health) {
1444
1466
  health.onclick = () => {
1445
- if (curPage !== 'companion') window.location.href = '/companion';
1467
+ if (curPage !== 'companion') navigateTo('/companion');
1446
1468
  };
1447
1469
  }
1448
1470
  if (kanban) {
1449
1471
  kanban.onclick = () => {
1450
- if (curPage !== 'kanban') window.location.href = '/kanban';
1472
+ if (curPage !== 'kanban') navigateTo('/kanban');
1451
1473
  };
1452
1474
  }
1453
1475
  if (tl) {
1454
1476
  tl.onclick = () => {
1455
- if (curPage !== 'timeline') window.location.href = '/timeline';
1477
+ if (curPage !== 'timeline') navigateTo('/timeline');
1456
1478
  };
1457
1479
  }
1458
1480
  if (graph) {
1459
1481
  graph.onclick = () => {
1460
- if (curPage !== 'graph') window.location.href = '/graph';
1482
+ if (curPage !== 'graph') navigateTo('/graph');
1461
1483
  };
1462
1484
  }
1463
1485
  if (docs) {
1464
1486
  docs.onclick = () => {
1465
- if (curPage !== 'docs') window.location.href = '/docs';
1487
+ if (curPage !== 'docs') navigateTo('/docs');
1466
1488
  };
1467
1489
  }
1468
1490
  }
@@ -2613,8 +2635,16 @@
2613
2635
  }
2614
2636
  }
2615
2637
 
2616
- // init
2617
- applyDarkTheme();
2638
+ // init — apply saved theme preference (default: light)
2639
+ (function initTheme() {
2640
+ var saved = null;
2641
+ try { saved = localStorage.getItem('freya-theme'); } catch(_) {}
2642
+ if (saved === 'dark') {
2643
+ document.documentElement.setAttribute('data-theme', 'dark');
2644
+ } else {
2645
+ document.documentElement.removeAttribute('data-theme');
2646
+ }
2647
+ })();
2618
2648
  const chipPort = $('chipPort');
2619
2649
  if (chipPort) chipPort.textContent = location.host;
2620
2650
  loadLocal();
@@ -3533,4 +3563,109 @@
3533
3563
  window.openBlockerEdit = openBlockerEdit;
3534
3564
  window.closeBlockerEdit = closeBlockerEdit;
3535
3565
  window.submitBlockerEdit = submitBlockerEdit;
3566
+
3567
+ /* ── Mobile Navigation Menu ── */
3568
+ var _mobileNavOpen = false;
3569
+
3570
+ function buildMobileNav() {
3571
+ // Only build on small screens and if not already built
3572
+ if (document.querySelector('.mobileMenuBtn')) return;
3573
+
3574
+ var curPage = (document.body && document.body.dataset) ? document.body.dataset.page : null;
3575
+ var isDashboard = !curPage || curPage === 'dashboard';
3576
+
3577
+ // Hamburger button
3578
+ var btn = document.createElement('button');
3579
+ btn.className = 'mobileMenuBtn';
3580
+ btn.setAttribute('aria-label', 'Menu de navegação');
3581
+ btn.innerHTML = '<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="3" y1="6" x2="21" y2="6"></line><line x1="3" y1="12" x2="21" y2="12"></line><line x1="3" y1="18" x2="21" y2="18"></line></svg>';
3582
+ btn.onclick = toggleMobileNav;
3583
+ document.body.appendChild(btn);
3584
+
3585
+ // Navigation overlay
3586
+ var nav = document.createElement('div');
3587
+ nav.className = 'mobileNav';
3588
+ nav.id = 'mobileNav';
3589
+ nav.onclick = function(e) {
3590
+ if (e.target === nav) closeMobileNav();
3591
+ };
3592
+
3593
+ var items = [
3594
+ { label: 'Dashboard', page: null, url: '/', icon: '<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="3" width="7" height="9"></rect><rect x="14" y="3" width="7" height="5"></rect><rect x="14" y="12" width="7" height="9"></rect><rect x="3" y="16" width="7" height="5"></rect></svg>' },
3595
+ { label: 'Relatórios', page: 'reports', url: '/reports', icon: '<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path><polyline points="14 2 14 8 20 8"></polyline></svg>' },
3596
+ { label: 'Companion', page: 'companion', url: '/companion', icon: '<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"></circle><polygon points="16.24 7.76 14.12 14.12 7.76 16.24 9.88 9.88 16.24 7.76"></polygon></svg>' },
3597
+ { label: 'Kanban', page: 'kanban', url: '/kanban', icon: '<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="3" width="5" height="18" rx="1"></rect><rect x="10" y="3" width="5" height="12" rx="1"></rect><rect x="17" y="3" width="5" height="15" rx="1"></rect></svg>' },
3598
+ { label: 'Projetos', page: 'projects', url: '/projects', icon: '<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2 3h9a2 2 0 0 1 2 2z"></path></svg>' },
3599
+ { label: 'Timeline', page: 'timeline', url: '/timeline', icon: '<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"></circle><polyline points="12 6 12 12 16 14"></polyline></svg>' },
3600
+ { label: 'Grafo', page: 'graph', url: '/graph', icon: '<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="18" cy="5" r="3"></circle><circle cx="6" cy="12" r="3"></circle><circle cx="18" cy="19" r="3"></circle><line x1="8.59" y1="13.51" x2="15.42" y2="17.49"></line><line x1="15.41" y1="6.51" x2="8.59" y2="10.49"></line></svg>' },
3601
+ { label: 'Configurações', page: 'settings', url: '/settings', icon: '<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="3"></circle><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09"></path></svg>' }
3602
+ ];
3603
+
3604
+ var panel = document.createElement('div');
3605
+ panel.className = 'mobileNav-panel';
3606
+
3607
+ for (var i = 0; i < items.length; i++) {
3608
+ var item = items[i];
3609
+ var isActive = item.page === curPage || (item.page === null && isDashboard);
3610
+ var el = document.createElement('button');
3611
+ el.className = 'mobileNav-item' + (isActive ? ' active' : '');
3612
+ el.innerHTML = item.icon + '<span>' + item.label + '</span>';
3613
+ el.setAttribute('data-url', item.url);
3614
+ el.onclick = function() {
3615
+ var url = this.getAttribute('data-url');
3616
+ navigateTo(url);
3617
+ };
3618
+ panel.appendChild(el);
3619
+ }
3620
+
3621
+ nav.appendChild(panel);
3622
+ document.body.appendChild(nav);
3623
+ }
3624
+
3625
+ function toggleMobileNav() {
3626
+ _mobileNavOpen ? closeMobileNav() : openMobileNav();
3627
+ }
3628
+
3629
+ function openMobileNav() {
3630
+ var nav = document.getElementById('mobileNav');
3631
+ var btn = document.querySelector('.mobileMenuBtn');
3632
+ if (!nav) return;
3633
+ nav.style.display = 'block';
3634
+ _mobileNavOpen = true;
3635
+ if (btn) btn.classList.add('open');
3636
+ // Trigger reflow for transition
3637
+ nav.offsetHeight;
3638
+ nav.classList.add('visible');
3639
+ }
3640
+
3641
+ function closeMobileNav() {
3642
+ var nav = document.getElementById('mobileNav');
3643
+ var btn = document.querySelector('.mobileMenuBtn');
3644
+ if (!nav) return;
3645
+ nav.classList.remove('visible');
3646
+ _mobileNavOpen = false;
3647
+ if (btn) btn.classList.remove('open');
3648
+ setTimeout(function() {
3649
+ nav.style.display = 'none';
3650
+ }, 250);
3651
+ }
3652
+
3653
+ // Build mobile nav on load
3654
+ buildMobileNav();
3655
+ window.closeMobileNav = closeMobileNav;
3656
+
3657
+ // Also intercept chip.clickable clicks for smooth transition
3658
+ document.querySelectorAll('.chip.clickable').forEach(function(el) {
3659
+ var href = el.getAttribute('onclick');
3660
+ if (href && href.indexOf('location.href') !== -1) {
3661
+ var match = href.match(/['"]([^'"]+)['"]/);
3662
+ if (match) {
3663
+ el.removeAttribute('onclick');
3664
+ el.onclick = function(e) {
3665
+ e.preventDefault();
3666
+ navigateTo(match[1]);
3667
+ };
3668
+ }
3669
+ }
3670
+ });
3536
3671
  })();
package/cli/web.js CHANGED
@@ -1572,7 +1572,7 @@ function buildReportsHtml(safeDefault, appVersion) {
1572
1572
  </button>
1573
1573
 
1574
1574
  </div>
1575
- <div class="railBottom">\n <button id="railSettings" class="railBtn" title="Configurações">\n <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="3"></circle><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z"></path></svg>\n </button>
1575
+ <div class="railBottom">\n <button id="railSettings" class="railBtn" title="Configurações" onclick="if (document.body.dataset.page !== 'settings') window.location.href='/settings';">\n <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="3"></circle><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z"></path></svg>\n </button>
1576
1576
 
1577
1577
  </div>
1578
1578
  </aside>
@@ -1931,7 +1931,9 @@ function buildTimelineHtml(safeDefault, appVersion) {
1931
1931
 
1932
1932
  </div>
1933
1933
  <div class=\"railBottom\">
1934
- <div class=\"railStatus\" id=\"railStatus\" title=\"status\"></div>
1934
+ <button id=\"railSettings\" class=\"railBtn\" title=\"Configurações\" onclick=\"if (document.body.dataset.page !== 'settings') window.location.href='/settings';\">
1935
+ <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="3"></circle><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z"></path></svg>
1936
+ </button>
1935
1937
  </div>
1936
1938
  </aside>
1937
1939
 
@@ -3061,7 +3063,7 @@ async function cmdWeb({ port, dir, open, dev }) {
3061
3063
  if (t.project_slug && nodeIds.has(t.project_slug)) {
3062
3064
  edges.push({ from: tid, to: t.project_slug });
3063
3065
  } else {
3064
- addNode('unassigned', 'Sin Asignar', 'unassigned');
3066
+ addNode('unassigned', 'Sem Atribuir', 'unassigned');
3065
3067
  edges.push({ from: tid, to: 'unassigned' });
3066
3068
  }
3067
3069
  }
@@ -4263,7 +4265,11 @@ async function cmdWeb({ port, dir, open, dev }) {
4263
4265
  const files = [
4264
4266
  path.join(rulesBase, 'freya.mdc'),
4265
4267
  path.join(rulesBase, 'agents', 'master.mdc'),
4266
- path.join(rulesBase, 'agents', 'oracle.mdc')
4268
+ path.join(rulesBase, 'agents', 'sm-agent.mdc'),
4269
+ path.join(rulesBase, 'agents', 'analytics-agent.mdc'),
4270
+ path.join(rulesBase, 'agents', 'oracle.mdc'),
4271
+ path.join(rulesBase, 'agents', 'coach.mdc'),
4272
+ path.join(rulesBase, 'agents', 'ingestor.mdc')
4267
4273
  ].filter(exists);
4268
4274
 
4269
4275
  const rulesText = files.map((p) => {
@@ -4296,7 +4302,7 @@ async function cmdWeb({ port, dir, open, dev }) {
4296
4302
  }
4297
4303
 
4298
4304
  // System instructions (small, always fits in -p)
4299
- const oracleSysInstr = `Você é o agente Oracle do sistema F.R.E.Y.A.\n\nSiga estritamente os arquivos de regras abaixo.\nResponda de forma analítica e consultiva.\n${ragContext}${imageContext}`;
4305
+ const oracleSysInstr = `Você é o Orchestrator do sistema F.R.E.Y.A.\n\nVocê NÃO é o Oracle. Você é o agente principal que COORDENA todos os sub-agentes.\nSiga o fluxo definido no master.mdc: analise o intent do usuário, execute o plano internamente (Oracle para buscar dados, SM Agent para sintetizar), e SEMPRE retorne uma resposta FINAL em linguagem natural, estruturada e consultiva para o usuário.\n\nNUNCA exponha JSONs brutos, hierarquia interna de agentes, ou peça ao usuário para "chamar outro agente".\nVocê DEVE sintetizar os dados recuperados em uma resposta clara, organizada e útil.\n\nIdioma: Português do Brasil.\n${ragContext}${imageContext}`;
4300
4306
 
4301
4307
  const cmd = process.env.COPILOT_CMD || 'copilot';
4302
4308
 
@@ -4331,7 +4337,7 @@ async function cmdWeb({ port, dir, open, dev }) {
4331
4337
  if (oracleTmpFile) { try { fs.unlinkSync(oracleTmpFile); } catch (_) { /* ignore */ } }
4332
4338
  const out = (r.stdout + r.stderr).trim();
4333
4339
  if (r.code !== 0) {
4334
- return safeJson(res, 200, { ok: false, answer: 'Falha na busca do agente Oracle:\n' + (out || 'Exit code != 0'), sessionId });
4340
+ return safeJson(res, 200, { ok: false, answer: 'Falha no processamento do agente FREYA:\n' + (out || 'Exit code != 0'), sessionId });
4335
4341
  }
4336
4342
  return safeJson(res, 200, { ok: true, answer: out, sessionId });
4337
4343
  } catch (e) {
@@ -5040,7 +5046,7 @@ function buildSettingsHtml(safeDefault, appVersion) {
5040
5046
  <span class="chip" style="font-weight:normal; font-size:11px;">Rules</span>
5041
5047
  </div>
5042
5048
  <div class="panelBody">
5043
- <p style="margin-top: 0; color: #666; font-size: 13px;">
5049
+ <p style="margin-top: 0; color: var(--muted); font-size: 13px;">
5044
5050
  A FREYA tenta adivinhar automaticamente a qual projeto uma tarefa pertence com base no LLM.
5045
5051
  Se você quiser <b>garantir</b> que uma palavra sempre caia em um projeto específico, adicione uma regra abaixo.
5046
5052
  </p>
@@ -5176,7 +5182,7 @@ function buildKanbanHtml(safeDefault, appVersion) {
5176
5182
  <button class="railBtn" id="railDashboard" type="button" title="Dashboard">
5177
5183
  <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="3" width="7" height="9"></rect><rect x="14" y="3" width="7" height="5"></rect><rect x="14" y="12" width="7" height="9"></rect><rect x="3" y="16" width="7" height="5"></rect></svg>
5178
5184
  </button>
5179
- <button class="railBtn" id="railReports" type="button" title="Relat\\u00f3rios">
5185
+ <button class="railBtn" id="railReports" type="button" title="Relatórios">
5180
5186
  <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path><polyline points="14 2 14 8 20 8"></polyline><line x1="16" y1="13" x2="8" y2="13"></line><line x1="16" y1="17" x2="8" y2="17"></line><polyline points="10 9 9 9 8 9"></polyline></svg>
5181
5187
  </button>
5182
5188
  <button class="railBtn" id="railCompanion" type="button" title="Companion">
@@ -5196,7 +5202,7 @@ function buildKanbanHtml(safeDefault, appVersion) {
5196
5202
  </button>
5197
5203
  </div>
5198
5204
  <div class="railBottom">
5199
- <button id="railSettings" class="railBtn" title="Configura\\u00e7\\u00f5es" onclick="if (document.body.dataset.page !== 'settings') window.location.href='/settings';">
5205
+ <button id="railSettings" class="railBtn" title="Configurações" onclick="if (document.body.dataset.page !== 'settings') window.location.href='/settings';">
5200
5206
  <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="3"></circle><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z"></path></svg>
5201
5207
  </button>
5202
5208
  </div>
@@ -5208,7 +5214,7 @@ function buildKanbanHtml(safeDefault, appVersion) {
5208
5214
  <span class="spark"></span>
5209
5215
  <div class="brandStack">
5210
5216
  <div class="brand">FREYA</div>
5211
- <div class="brandSub">Kanban Board &mdash; Vis\\u00e3o SM</div>
5217
+ <div class="brandSub">Kanban Board &mdash; Visão SM</div>
5212
5218
  </div>
5213
5219
  </div>
5214
5220
  <div class="topActions">
@@ -5310,7 +5316,7 @@ function buildKanbanHtml(safeDefault, appVersion) {
5310
5316
  <span style="font-weight:700; font-size:14px;">Nova Task</span>
5311
5317
  <button class="btn small" type="button" onclick="window.closeQuickAdd()" style="padding:2px 8px;">&times;</button>
5312
5318
  </div>
5313
- <textarea id="qaDesc" class="qa-input" placeholder="Descri\\u00e7\\u00e3o da task..." rows="3"></textarea>
5319
+ <textarea id="qaDesc" class="qa-input" placeholder="Descrição da task..." rows="3"></textarea>
5314
5320
  <div class="qa-row">
5315
5321
  <select id="qaCat" class="qa-select">
5316
5322
  <option value="DO_NOW">DO_NOW</option>
@@ -5319,9 +5325,9 @@ function buildKanbanHtml(safeDefault, appVersion) {
5319
5325
  </select>
5320
5326
  <select id="qaPriority" class="qa-select">
5321
5327
  <option value="">Prioridade</option>
5322
- <option value="critical">Cr\\u00edtica</option>
5328
+ <option value="critical">Crítica</option>
5323
5329
  <option value="high">Alta</option>
5324
- <option value="medium">M\\u00e9dia</option>
5330
+ <option value="medium">Média</option>
5325
5331
  <option value="low">Baixa</option>
5326
5332
  </select>
5327
5333
  </div>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cccarv82/freya",
3
- "version": "3.4.1",
3
+ "version": "3.5.1",
4
4
  "description": "Personal AI Assistant with local-first persistence",
5
5
  "scripts": {
6
6
  "health": "node scripts/validate-data.js && node scripts/validate-structure.js",