223 Commits

Author SHA1 Message Date
56cae559b4 chore: auto-commit from dashboard 2026-09-13 11:09:29 +00:00
553a137206 chore(kb): note noi (youtube, facebook, fișe grup sprijin, email) + tool scout_voluntar_check
Reindexare KB, timestamps cron/habits actualizate din rulările automate.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-10 08:53:49 +00:00
1f0ed3ca12 chore(doctor): prefix "Steering:" pe verificarea --input-format
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SiJGsZVSEGjRHZEJiXaxCC
2026-09-02 12:52:15 +00:00
1c8e024aea fix(doctor): health check WhatsApp prin /status, nu grep pe log
Bridge-ul Baileys scrie erori tranzitorii, non-fatale (timeout pe query-uri
interne de init) la nivel pino 50 chiar și conectat — verificarea "ultima
linie de log conține 'error'" le raporta ca eșec. /status e ce consideră
bridge-ul însuși despre starea lui.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SiJGsZVSEGjRHZEJiXaxCC
2026-09-02 12:52:15 +00:00
d778d097d8 fix(logging): rotație echo-core.log + oprire scriere dublă
Loggerul `echo-core.invoke` avea handler propriu pe echo-core.log ȘI
propagare la root handler pe același fișier — fiecare linie scrisă de
două ori. La fel `echo-core.security`, scris și în security.log și în
echo-core.log. Împreună, 1.2GB de log.

- handler propriu pentru invoke: eliminat (propagarea la root ajunge)
- security_logger.propagate = False
- FileHandler → RotatingFileHandler (50MB × 5 backups)

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SiJGsZVSEGjRHZEJiXaxCC
2026-09-02 12:05:18 +00:00
2ba238bb01 chore(cron): timestamps de rulare scrise de scheduler
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SiJGsZVSEGjRHZEJiXaxCC
2026-09-02 11:06:03 +00:00
8e8c92d272 docs(kb): notițe noi (fiscal micro vs profit, 3 video) + reindexare
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SiJGsZVSEGjRHZEJiXaxCC
2026-09-02 11:06:03 +00:00
747afbaf9d feat(steering): mesaje mid-tur + /stop pe turul în zbor
Un al doilea mesaj trimis cât Claude încă lucra aștepta până se termina
turul 1 — corecția „stai, nu în master" ajungea după ce greșeala era gata.
Verificat în producție înainte de commit: mesajul 2 stătea 25s blocat în
lock, apoi pornea ca tur separat.

Acum canalele de chat pot ține un proces `claude` viu per canal, cu stdin
deschis, și al doilea mesaj intră în ACELAȘI tur.

- `src/claude_runner.py` — ClaudeProcess (steering, respawn cu --resume,
  drenare stderr, respawn la comutarea OpenRouter) + RunnerRegistry
  (max_live, reaper pe inactivitate, stop_all la shutdown)
- `src/stream_json.py` — parser stream-json partajat cu `_run_claude`;
  pur, nu aruncă niciodată pe is_error (PlanningSession retrimite pe
  error_max_turns și depinde de asta)
- `src/sentinels.py` — un singur loc pentru __AUDIO__/__STEERED__, în loc
  de 4 verificări copiate; repară și bug-ul preexistent prin care
  WhatsApp posta literal `__AUDIO__:/cale`
- dispecer în `send_message`: lock.acquire(blocking=False) — eșecul de a
  lua lock-ul ESTE „rulează un tur", ceea ce elimină flagul inflight din
  decizie și cursa TOCTOU odată cu el
- `/stop` oprește turul, nu sesiunea — active.json rămâne valid
- rate limit prin proces persistent vine ca result.is_error, nu ca exit
  code; convertit înapoi în același RuntimeError, altfel fallback-ul
  local nu s-ar mai declanșa niciodată, în tăcere

Steering-ul nu face niciodată cross-adapter (un mesaj text nu intră
într-un tur voice: împart același channel_id). Mesajele steered dintr-un
tur care pică sunt re-livrate, nu pierdute.

Testat live cu CLI-ul real: corecție la secunda 10 dintr-un tur de 24s,
un singur result, num_turns=2. Notă: mesajele steered sunt împachetate în
[EXTERNAL CONTENT], deci o corecție formulată ca override agresiv poate
fi refuzată ca prompt injection — pentru oprire folosește /stop.

Suită: 1199 passed, 12 failed (toate pre-existente pe HEAD curat).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SiJGsZVSEGjRHZEJiXaxCC
2026-09-02 11:05:58 +00:00
2d8ee9b581 feat(dashboard): login-ul cu token, dezactivat implicit
Accesul la /echo trece deja prin `tailscale serve` (tailnet only), deci
formularul de token era o a doua autentificare peste una existentă.

`DASHBOARD_AUTH` nesetat => `_check_dashboard_cookie` trece mereu: paginile
.html nu mai redirectează la /echo/login, POST-urile /api/* nu mai dau 401,
iar /echo/login sare direct la destinație. Codul de login rămâne intact —
`DASHBOARD_AUTH=on` în dashboard/.env îl reactivează neschimbat.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0188YmDTUAzVvZDVh8JL8xSa
2026-08-31 22:11:39 +00:00
a62e4d4ab7 fix(gitignore): tipare de secrete, ca auto-commit-ul să nu mai publice credențiale
Dashboard-ul face `git add -A` + commit + push fără intervenție umană
(dashboard/handlers/git.py:110). Regulile pe nume exact acopereau doar fișierele
observate, nu clasele lor: `bridge/whatsapp/auth/` era ignorat, dar
`auth.bak-*/` nu — așa a ajuns creds.json cu chei de sesiune WhatsApp pe Gitea.

Audit: din 21 de nume plauzibile testate (.env.local, credentials.json, token.json,
id_rsa, auth-old/, server.pem, cookies.txt, dump.sql, config.json.bak, nohup.out),
toate 21 treceau nestingherite. Acum toate sunt prinse.

- bridge/whatsapp/auth*/ acoperă orice variantă de director de stare Baileys
- .env* (cu excepție pentru .env.example), *.pem, *.key, id_rsa*, id_ed25519*
- *token*.json, *credential*.json, client_secret*.json, creds.json, cookies*.txt
- backup-uri/dump-uri: *.bak, *.backup, *.orig, *.dump, *.sql, *.tar.gz, *.zip,
  *.bundle — cu !memory/kb/**/*.bak pentru notițele legitime din KB
- nohup.out, core.[0-9]*

Verificat în ambele direcții: `git ls-files | git check-ignore --stdin` nu
întoarce nimic (niciun fișier tracked nu devine ignorat), iar cele 21 de nume
ipotetice sunt acum toate ignorate.

Restul auditului e curat: zero secrete în fișierele tracked, config.json fără
credențiale (keyring folosit corect), credentials/, dashboard/.env,
memory/echo.sqlite și bridge/whatsapp/auth/ deja acoperite.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0188YmDTUAzVvZDVh8JL8xSa
2026-08-31 22:04:58 +00:00
c08d4f8678 docs(kb): notițe active recall recuperate + reindexare
Cele două linkuri Facebook din 31 aug erau video-uri DIFERITE, nu unul singur —
de aceea retry-urile au produs duplicate în loc să acopere ambele.

- adaugă „How to Do ACTIVE RECALL Effectively" (Simple, actually, 9:14) și
  „How to Study & Learn Using Active Recall" (Huberman × Cal Newport, 5:39),
  transcrise corect în engleză, cu TL;DR completat
- șterge 807k-views-15k-reactions.md și 810k-views-15k-reactions.md: ambele erau
  același link, transcrise cu `ro` forțat pe audio englezesc (text halucinat)
- adaugă nota YouTube din 29 aug rămasă necomisă
- reindexare via tools/update_notes_index.py

cron/: bookkeeping de last_run/next_run scris de scheduler.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0188YmDTUAzVvZDVh8JL8xSa
2026-08-31 21:52:41 +00:00
cb2eedac86 fix(transcribe): rulare detașată, ca joburile video să nu mai moară la timeout
Două linkuri Facebook trimise pe Discord n-au produs niciun răspuns: scriptul
rula în interiorul turnului de chat, iar yt-dlp + ffmpeg + whisper depășeau
constant DEFAULT_TIMEOUT (300s, src/claude_session.py:37). Procesul era omorât
la mijlocul transcrierii, de cinci ori pe patru încercări.

Efecte în cascadă, toate reparate aici:
- retry-uri oarbe: linkul 1 reprocesat de două ori (notițe duplicate), linkul 2
  niciodată atins
- notițe cu TL;DR gol — arată „gata" în index dar nu sunt
- orfani de 33MB în /tmp (trap EXIT nu rulează la SIGKILL)
- userul nu primea nici rezultat, nici eroare acționabilă

Schimbări:
- --bg (setsid nohup) + --notify <channel_id>; turnul confirmă pornirea, nu
  terminarea. send_text() nou în tools/discord_send_file.py, pentru că un job
  detașat supraviețuiește turnului și nu mai poate raporta prin on_text.
- faster-whisper int8 în locul openai-whisper: 554s audio în 113s (~5x realtime)
  vs. peste 300s. Era deja în requirements.txt; openai-whisper nici măcar nu era
  declarat. cpu_threads pe core-uri fizice, nu logice.
- limba implicită „auto": rularea forțată cu `ro` pe audio englezesc producea
  transcriere halucinată (română inventată amestecată cu CJK)
- .venv/bin/python3 explicit; whisper nu există în python-ul de sistem, scriptul
  mergea doar când era chemat cu venv-ul activat
- metadata yt-dlp pe disc, parsată o dată: descrierile Facebook conțin caractere
  de control care corup variabila de shell, iar `|| echo Unknown` masca eșecul
- titlul sare segmentele de statistici: Facebook emite „830K views · 15K
  reactions | Titlul real | Pagina", iar split('|')[0] producea notițe numite
  2026-08-31_807k-views-15k-reactions.md
- curăță workdir-urile orfane mai vechi de 60 min la pornire

.gitignore: bridge/whatsapp/auth.bak-*/ — backup-urile Baileys conțin creds.json
(chei de sesiune vii), la fel ca auth/ care era deja ignorat.

Verificat end-to-end pe ambele linkuri: titlu corect, limbă en auto-detectată,
notiță + reindex + link, trap curăță /tmp, zero orfani.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0188YmDTUAzVvZDVh8JL8xSa
2026-08-31 21:52:30 +00:00
9b01f52dfa docs(kb): document VM 109 SSH-key gap in DR failover, restore correct host
VM 109 a ajuns pe pvemini pe 27 aug fara ca root-ul de acolo sa aiba cheia
SSH autorizata pe Windows guest, ceea ce a stricat testul DR saptamanal
(eroare de auth SSH mascata drept "NFS/restore failed"). Migrat inapoi pe
pveelite (unde cheia originala functioneaza) si documentat gap-ul structural
din procedura de failover/migrare pentru viitor.
2026-08-29 12:42:33 +00:00
bf62d6fb4b feat(dashboard): endpoint de download fișiere binare + tool epub-to-audio
- dashboard/handlers/files.py: handle_files_download() servește mp3/wav/zip
  din WORKSPACE_DIR cu Content-Disposition attachment, resolve dedicat
  (nu _resolve_sandboxed, care nu ajunge niciodată la WORKSPACE_DIR)
- dashboard/api.py: rutează /api/files/download
- tools/epub_to_audio.py: tool nou de conversie EPUB → audio
- cron/jobs.json, memory/kb/index.json: stare auto-generată (job runs,
  regenerare index KB)

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-27 17:50:27 +00:00
164ff32031 fix(memory): retry cu split la eroare de context Ollama in indexare KB
Chunk-urile mari (tabele dense cu IP-uri/cod) treceau de split-ul pe
paragrafe dar depaseau limita reala de tokeni a all-minilm, nu doar
un prag fix de caractere — 18/20 chunk-uri din infrastructure.md
esuau silentios la fiecare heartbeat. embed_chunk() acum injumatateste
textul recursiv la eroare 500 si retrimite pana reuseste.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-27 17:30:29 +00:00
b97edd5184 fix(fallback): turnul nu se mai pierde cand Claude e la limita
Detectia de rate limit functiona, dar `_local_fallback_reply` putea
intoarce None din patru locuri fara nicio linie de log — userul primea
`Claude CLI error (exit 1): You've hit your session limit` pe Discord in
loc de raspuns, si nu se putea afla ulterior din log care branch a picat.

- daca runda de unelte iese goala, turnul se reface fara unelte in loc
  sa fie abandonat
- fiecare return None ramas e logat
- daca nici modelul local nu raspunde, mesajul e „Claude e la limita…"
  plus ora de reset, nu eroarea bruta a CLI-ului
- cron: job-urile heartbeat* tac la limita (last_status: rate_limited);
  celelalte trimit o singura linie scurta, ca sa se vada rularea sarita
- is_rate_limit_error / rate_limit_detail mutate in claude_session.py,
  folosite si de scheduler (care nu poate importa router-ul)

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DzZAMzbyQbzFdsrVoXijBg
2026-08-23 14:52:44 +00:00
a1d39637c8 feat(fallback): unelte, internet, retea si conversatie pe modelul local
Fallback-ul local (Qwen3.5-2B, LXC 104) raspundea ca nu are unelte sau
internet. Acum conversează, are unelte read-only si istoric per canal.

Unelte (allowlist strict read-only, src/local_fallback_tools.py):
- cauta_web — DuckDuckGo Lite, fara API key
- masini — status Proxmox/LXC prin SSH paralel (src/net_status.py)
- vremea, sold, facturi, trezorerie, doctor, logs, email, kb,
  cauta_memorie, citeste_pagina

Protocol: function calling OpenAI nativ. Protocolul text anterior
("TOOL: nume arg") pierdea argumentul in 100% din cazuri.

Uneltele cu output deja formatat se intorc verbatim — modelul de 2B
transforma un `doctor` cu 5 linii OK in "Sistemul este in 5/5 state.".

Doua treceri: prima decide uneltele (cu tools, temp 0), a doua reface
turnul fara ele — prezenta definitiilor strica raspunsurile simple
("cat fac 128/4?" -> "Nu stiu ce inseamna 128/4"). Few-shot doar pe
cereri creative: pe turnuri factuale strica aritmetica (17*23 -> 471).

Ocoliri deterministe pentru ce modelul greseste reproductibil: vremea si
preturile live (raspundea din memorie), plus sarcini "instructiune: text"
(payload-ul dicta unealta — "scrie mai politicos: da-mi raportul acum"
chema `sold`). llama.cpp nu e determinist nici la temperatura 0 si
ignora tool_choice, deci promptul singur nu ajunge.

Masurat: 36/36 pe set combinat (17 alegere unealta + 19 comprehensiune),
de la 14/19 pe comprehensiune inainte de regulile negative din prompt.

Comenzi: /f (inlocuieste /testfallback, ramas alias), /f reset, /masini.
Prefixul "Claude e la limita" apare doar pe calea de rate limit.

roa2web: /otp <cod> pentru 2FA din chat — mesajul de eroare trimitea la
verify_2fa(code, email), imposibil de rulat din Discord.

Corectat memory/kb/tools/infrastructure.md: LXC 101 si 110 sunt pe pve1.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01B88u3KkzvUNnzU56y7GBn2
2026-08-23 07:46:46 +00:00
fe500a7227 chore: auto-commit from dashboard 2026-08-22 08:40:56 +00:00
4d2dbfb8a7 chore: auto-commit from dashboard 2026-07-12 19:28:42 +00:00
80eb8034b3 fix(voice): instrucțiune de limbă inline + fallback Supertonic pe română
Markerul opac [tts-lang:en] depindea de regula din VOICE_MODE.md, aflată
la ~30k caractere distanță în system prompt — modelul o rata pe ~1 din 5
turnuri. Răspunsul în română era apoi respins integral de pocket-tts
(English-only) și turnul rămânea fără audio.

- src/router.py: markerul poartă instrucțiunea inline (un singur token,
  acoperit în continuare de strip-ul anti-jailbreak); 5/5 EN la repro
- src/voice/tts_stream.py: dacă modelul tot scapă română pe o voce
  pockettts, blocul cade pe Supertonic (M2, ro) în loc de tăcere;
  coada TTS transportă (clause, voice, lang) per clauză
- tools/tts.py: looks_romanian public (folosit de tts_stream)
- personality/VOICE_MODE.md: regula gated pe prefixul [tts-lang:en
- tests: 4 teste noi fallback + expectații marker actualizate

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-11 19:20:28 +00:00
61d667ec65 fix(voice): normalizare TTS lang-aware + cap 400 chars mutat per-request Supertonic
Două cauze pentru audio mut pe pocket-tts după fix-ul [tts-lang:en]:

1. normalize_for_tts expanda numerele/orele în cuvinte românești chiar și
   în text englezesc ("It's 9:46 PM" → "nouă și patruzeci și șase de
   minute") → diacritice → pocket-tts respingea clauzele. push_text rezolvă
   acum lang din engine-ul vocii curente (engine_for_voice) și sare
   expansiunile RO când lang != 'ro'. [scris de Echo în sesiunea Discord]

2. sanitize_for_supertonic (cap 400 chars — limită ONNX per request) rula
   pe textul întreg în normalize, înainte de segmentarea în clauze —
   răspunsurile lungi erau retezate mid-word și trunchierea la 200 cuvinte
   cu sufixul "Restul l-am scris în chat" nu se mai aplica. Separat
   map_tts_punctuation (fără cap, folosit de normalize) de
   sanitize_for_supertonic (cap, aplicat în _synthesize_supertonic).

Include vocea clonată "Marius 4" (tts_voices.json + default în config).

Fixează test_truncate_exactly_200_words_unchanged și
test_truncate_over_200_words_appends_suffix.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-11 18:57:30 +00:00
00e0d1ad8c fix(voice): răspuns în engleză pe voice turns când vocea activă e pocket-tts
Instrucțiunea „engleză pentru audio" nu ajungea la model: VOICE_MODE.md nu
avea nicio regulă de limbă, iar condiția din TOOLS.md („când generez pentru
o voce pockettts") era neevaluabilă — modelul nu știa ce voce e activă.
Rezultat: mirroring pe română → filtrul de diacritice bloca sinteza → tăcere.

- tools/tts.py: helper public engine_for_voice() (catalog → tts.default_engine)
- src/router.py: injectează [tts-lang:en] în prefixul voice când vocea activă
  e pockettts (config citit fresh — vede swap-ul live /voice setvoice);
  anti-jailbreak strip extins la [tts-lang:...]
- personality/VOICE_MODE.md: regulă de limbă gated pe marker
- tests/test_router.py: 5 teste noi pentru marker + strip

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-11 18:07:14 +00:00
321bd49ce6 chore: auto-commit from dashboard 2026-07-11 17:30:26 +00:00
00ac971044 fix(tts): pocket-tts refuză text cu diacritice RO în loc să-l pronunțe greșit
Kyutai pocket-tts nu suportă română (vezi eval anterior). Codul rula
oricum sinteza pe orice text primit; acum _synthesize_pockettts
respinge diacriticele RO înainte de request, fără fallback silențios
pe altă voce.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-11 17:30:12 +00:00
a043e2f177 feat: US-011, US-012 - teste TTS + documentație /voice
Finalizare manuală după ce ralph.sh a epuizat bugetul de 15 iterații
la 10/12 povești (self-improve TTS pocket-tts + Supertonic).

- tests/test_tts.py: rutare engine din catalog, fallback tehnic vs
  eroare de conținut, regression retry lang=na
- tests/test_config.py: test dedicat persistență tts.default_engine
- personality/TOOLS.md: documentează /voice engine, setvoice,
  addvoice, doctor și /audio

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-11 16:59:41 +00:00
9ddad02879 feat: US-010 - marchează complet în prd.json
Actualizează prd.json (passes:true, notes) și progress.txt cu rezultatele
gate-urilor pentru US-010.
2026-07-11 11:16:39 +00:00
c1414616ad feat: US-010 - Extinde /voice doctor cu health-check pocket-tts
- adaugă ping GET /health la pocket-tts (URL din config tts.pockettts_url)
- adaugă verificare prezență hf_token în keyring
- checks-urile existente (libopus, voice load error) rămân neschimbate

gates rulate: tests PASS (1043 passed, 22 preexistente neschimbate), /review (backend) manual PASS
2026-07-11 11:16:06 +00:00
8700276816 feat: US-009 - marchează complet în prd.json 2026-07-11 10:44:06 +00:00
504e12ac4e feat: US-009 - Autocomplete voci din catalog pentru /audio și /voice setvoice
- tools/tts.py: +list_voice_names(engine=None), sursă live din tts_voices.json
- src/fast_commands.py: _VOICES statice -> _supertonic_voice_names() din catalog
- discord_bot.py /audio și discord_voice.py /voice setvoice: choices statice -> autocomplete live
- gates rulate: tests PASS (1043 passed, 22 eșecuri preexistente neschimbate), ui/backend review PASS manual
2026-07-11 10:44:04 +00:00
3d5c2a4ace feat: US-008 - Comandă Discord /voice addvoice
- /voice addvoice <nume> <sample:Attachment>: validează wav+durată min 3s,
  oprește pocket-tts.service, exportă vocea prin pocket_tts_add_voice.py
  în venv separat, repornește serviciul, răspunde cu numele final + preview audio
- gates rulate: tests PASS (1043 passed, 22 preexistente neschimbate), review backend manual PASS
2026-07-11 10:38:15 +00:00
c7db236247 feat: US-007 - Comandă Discord /voice engine
- Comandă nouă /voice engine <pockettts|supertonic> setează tts.default_engine în config, persistă via Config().set+save()
- Helper _default_voice_for_engine() confirmă vocea implicită a engine-ului ales (alba pentru pockettts, voice.default_voice pentru supertonic)
- Gates: pytest PASS (22 eșecuri preexistente neschimbate), review manual PASS, wiring comandă verificat izolat (fără restart pe bot-ul live)
2026-07-11 10:31:38 +00:00
7ede30d156 feat: US-006 - Refactor tools/tts.py — rutare engine, backend pocket-tts și fallback
- synthesize() rezolvă engine din tts_voices.json (fallback la tts.default_engine din config)
- _synthesize_pockettts nou: POST multipart la :7789/tts cu voice_wav/voice_url, ignoră lang
- fallback tehnic automat pe _synthesize_supertonic(M2, ro) via _PocketTTSUnavailable; erori de
  conținut (voce lipsă, text gol) nu declanșează fallback; rezultatul include engine_used
- gates rulate: tests PASS (1043 passed, 22 eșecuri preexistente neschimbate), /workflow:simplify
  (4 agenți) cu 1 fix aplicat, /review (backend, manual) PASS
2026-07-11 10:28:06 +00:00
90b1fbdffe feat: US-005 - marchează complet în prd.json
- US-005 (config.json secțiune tts) verificat și marcat passes:true
2026-07-11 10:17:23 +00:00
e14a2d7189 feat: US-005 - Adaugă secțiunea tts în config.json
- config.json: secțiune tts nouă (default_engine=pockettts, pockettts_url=http://127.0.0.1:7789)
- gates rulate: tests PASS (1043 passed, 22 eșecuri preexistente neschimbate), review manual PASS (diff data-only, Config deja generic)
2026-07-11 10:17:09 +00:00
6e73887867 feat: US-004 - Script de export voce pocket_tts_add_voice.py
- tools/pocket_tts_add_voice.py fusese deja creat și commitat cu US-003
  (e3b5cdf); acest commit doar marchează US-004 complet în prd.json după
  verificare
- verificat: script rulează cu .venv-pockettts/bin/python fără .venv
  principal; _next_free_index întoarce 4 pentru Marius/Paula existenți
  (1-3 ocupate), 1 pentru nume noi
- verificat integritatea celor 6 blob-uri models/voices/*.safetensors deja
  exportate (12 tensori fiecare, safetensors.torch.load_file OK)
- gates: /review (backend) PASS, pytest 1043 passed (22 eșecuri
  preexistente neschimbate)
2026-07-11 10:15:07 +00:00
e3b5cdf0e5 feat: US-003 - Creează catalogul de voci tts_voices.json cu seed inițial
- tts_voices.json (nou): seed 17 intrări — M1-M5/F1-F5 supertonic, Marius 1-3
  și Paula 1-3 pockettts (state_path spre models/voices/*.safetensors), alba
  pockettts (voice_url)
- .gitignore: +*.lock pentru sidecar-uri jsonlock
- elimină approved-tasks.json.lock din git (sidecar gol, jsonlock îl recreează)
- scris prin src/jsonlock.py write_locked()
- gates: /review (backend) PASS, db (schema manuală) PASS, pytest 1043 passed
  (22 eșecuri preexistente neschimbate)
2026-07-11 10:14:40 +00:00
18c05ede39 feat: US-002 - Adaugă hf_token la verificarea de secrete în credential_store
- REQUIRED_SECRETS include acum hf_token alături de discord_token
- teste actualizate pentru noul set de secrete obligatorii (+ test_partial_required)
- gates rulate: tests PASS (22 eșecuri preexistente neschimbate), /review (backend) PASS
2026-07-11 10:05:05 +00:00
ed407b49a6 feat: US-001 - Setup venv-pockettts și pocket-tts.service systemd unit
- venv separat .venv-pockettts (torch + pocket-tts + keyring), gitignored
- tools/pocket_tts_env_launch.sh citește hf_token din keyring, exit non-zero + log clar dacă lipsește
- pocket-tts.service (systemd --user) pornește serverul built-in pe 127.0.0.1:7789 prin launcher
- gates: /review (manual, diff minimal) PASS, smoke test curl /health 200 + restart test PASS
2026-07-11 10:02:26 +00:00
155d6cb9c1 Update TOOLS.md, cron jobs, KB index; add discord file sender + pocket-tts plan
Pre-existing work committed before starting Ralph self-improvement run on
ralph/echo-improve branch, so that branch's diff stays isolated to the
pocket-tts integration.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-11 09:54:36 +00:00
738dc0181a chore: auto-commit from dashboard 2026-07-10 15:12:22 +00:00
7b44749e5a fix(newsletter): elimină jobul APScheduler intern duplicat și bugged
Jobul intern rula pe zile greșite (vineri/sâmbătă/marți în loc de
joi/vineri/luni) din cauza convenției diferite de day-of-week dintre
APScheduler și crontab standard. Scriptul standalone via OS crontab
e mecanismul corect și funcțional — rămâne singura sursă.

chore: sync stare working-tree — cron, KB notes, anaf-monitor snapshots
2026-07-09 14:54:15 +00:00
d175d5ba5a chore: working-tree state — anaf snapshots, cron state, KB notes, tools
Pre-existing uncommitted changes swept in with the STT work:
anaf-monitor snapshots/versions, cron job + newsletter state, 9 youtube KB
notes, tools/ocr_bon.py, and tools/tts.py.

Note: the tts.py change breaks 2 truncation tests in test_voice_normalize.py
(sanitize word-count) — flagged for a separate follow-up.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-27 18:16:31 +00:00
ce273d14db feat(voice): improve Romanian STT — hallucination gate + finetuned model
Gemma 4 cloud audio was infeasible (31b-cloud has no audio; E4B broken
upstream, no deploy host), so improve faster-whisper instead.

- Pin temperature=0.0 to disable the fallback ladder that re-decoded unclear
  audio up to 6x (source of the 16-24s latency outliers); reject hallucinated
  segments via avg_logprob/compression_ratio in the new pure _filter_segments.
- Adopt mikr/whisper-small-ro-cv11 (CT2 int8) via configurable voice.stt_model:
  spike showed WER 24%->10%, numbers fixed at source, +0.33s p50 (in budget).
- Add tools/voice_stt_mine.py (log mining) + tools/voice_stt_spike.py (model
  eval with diacritic scoring) + tests for the gate and miner.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-27 18:16:16 +00:00
ec23d188ec feat: youtube handler analizeaza cu Claude; nota Grantham completă
- dashboard/handlers/youtube.py: după descărcare transcriere, cheamă
  `claude -p` cu un prompt structurat care generează TL;DR + puncte cheie
  + citate + idei acționabile + secțiuni tematice în proze. Fallback la
  transcriptul brut dacă Claude eșuează.
- nota Grantham: format complet — TL;DR, puncte cheie, citate,
  idei acționabile, secțiuni tematice în proze curgătoare.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-27 18:03:29 +00:00
392d1a5be2 fix: nota Grantham rescrisă în proze curgătoare cu conținut real
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-27 18:00:09 +00:00
c8be07b1f6 Merge branch 'feat/kb-navigation-index' into voice/stt-quality
# Conflicts:
#	memory/kb/index.json
2026-06-27 17:57:22 +00:00
97e34be863 fix: nota Grantham include transcriptul complet (60k chars)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-27 17:55:38 +00:00
5c9748ffb4 feat(memory): hybrid retrieval — navigation index.md + RAG hardening
Expose a navigation layer to the agent and harden RAG, after analyzing the
OKF note and testing on the real KB.

- memory_search.search(): dedupe best-chunk-per-file (a relevant note can no
  longer be buried by another file's chunks) + keyword fallback tagged
  degraded:True when Ollama is unreachable (no more hard crash).
- update_notes_index.py: emit per-folder index.md + root router; prune empty
  folders; fix latent subcategory->project bug.
- Exclude generated index.md from RAG rglob (reindex/incremental) + indexer
  scans + heartbeat freshness check (prevents self-pollution / reindex thrash).
- CLAUDE.md: reframe memory as hybrid (navigation first, RAG for fuzzy recall).
- Delete stale orphan kb/youtube/index.json; correct the OKF source note.
- Tests: dedup, keyword fallback, index.md exclusion. Plan + review in docs/.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-27 17:52:27 +00:00
6e9dfd137c feat: youtube_subs + dashboard includ descrierea video ca index
- tools/youtube_subs.py: get_subtitles() returneaza acum (title, desc, transcript).
  Functii noi is_description_about_video() si extract_relevant_description()
  detecteaza daca descrierea contine capitole/timestamps (nu doar promotie autori)
  si curata trailing-urile promotionale inainte sa includa descrierea in output.
- dashboard/handlers/youtube.py: aceleasi functii adaugate; nota KB generata
  include acum un bloc "Descriere / Index" daca descrierea e relevanta pentru video.
- memory/kb/youtube: nota Jeremy Grantham (AI bubble, investitii, toxicitate)
  cu descrierea ca index de capitole.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-27 17:00:59 +00:00
a8d024944d chore: auto-commit from dashboard 2026-06-09 09:13:35 +00:00