Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KddsXCqEbKMhdFJDYbAsx8
258 lines
16 KiB
Markdown
258 lines
16 KiB
Markdown
# TODO — progresul funcționalităților
|
||
|
||
Registrul viu al lucrului cerut prin puntea Discord. **Botul îl citește la începutul
|
||
oricărei cereri de dezvoltare și îl actualizează la final** — vezi
|
||
[docs/flux-dezvoltare.md](docs/flux-dezvoltare.md).
|
||
|
||
Stări: `🔵 planificat` · `🟡 în lucru` · `⛔ blocat` · `✅ gata` · `❌ abandonat`
|
||
|
||
---
|
||
|
||
## 🟡 În lucru
|
||
|
||
*(nimic în acest moment)*
|
||
|
||
---
|
||
|
||
## ⛔ Blocate
|
||
|
||
*(nimic blocat)*
|
||
|
||
---
|
||
|
||
## 🔵 Planificate
|
||
|
||
### Maria — termenii distinctivi se judecă pe interogarea combinată, nu pe întrebare
|
||
- **Unde:** `romfastsql/proxmox/lxc171-claude-agent/maria-whatsapp-bridge/`
|
||
(`rag/rank.py:168 rare_terms`, `rag/consumer.py:144`, `ops/calibrate-rank.py`)
|
||
- **Ce ar însemna:** pe un fir, căutarea se face după ancoră + mesajul nou, iar
|
||
acoperirea se judecă pe același text. Rezultatul: „buna", „luna", „august" din
|
||
primul mesaj ajung „termeni distinctivi" și nu apar niciodată în documente, deci
|
||
raportul cerut de `assess()` scade la fiecare replică → escaladare în plus pe
|
||
discuțiile lungi. Regăsirea trebuie să rămână pe interogarea combinată;
|
||
acoperirea să treacă pe mesajul nou.
|
||
- **Întâi:** cazuri de continuare **fără cod de eroare** în `ops/calibrate-rank.py`
|
||
(azi are 26, toate continuările au cod, deci trec pe altă regulă). Fără ele nu se
|
||
poate valida reparația — continuările scurte („da, mă blochează") n-au termeni
|
||
distinctivi proprii și riscă să escaladeze, exact regresia pentru care există firul.
|
||
- **De ce nu acum:** direcția de eșec e sigură (escaladare, nu răspuns inventat) și
|
||
nu există încă nicio dovadă că se produce în practică.
|
||
- **Context complet:** `romfastsql/CONTEXT_HANDOVER_20260901_termeni_distinctivi.md`
|
||
- **Actualizat:** 2026-09-01
|
||
|
||
### Mesaje vocale din Discord
|
||
- **Unde:** `romfastsql/proxmox/lxc171-claude-agent/discord-bridge/bot.py`
|
||
- **Ce ar însemna:** atașamentele audio (mesajele vocale Discord) transcrise local
|
||
înainte de a intra în prompt. Whisper rulează pe CPU pe LXC 171, deci trebuie
|
||
măsurat întâi costul în timp per mesaj.
|
||
- **De ce nu acum:** nu a fost cerut; e singura limitare rămasă după atașamente.
|
||
- **Actualizat:** 2026-08-31
|
||
|
||
---
|
||
|
||
## ✅ Gata
|
||
|
||
### Infrastructură în dashboard + `/infra` în Discord
|
||
- **Unde:** `romfastsql/proxmox/lxc171-claude-agent/discord-bridge/` (`infra_actions.py` nou,
|
||
`dashboard/`, `bot.py`, `commands_slash.py`), `romfastsql/proxmox/cluster/scripts/`,
|
||
`romfastsql/proxmox/cluster/ups/scripts/`
|
||
- **Ce:** tab „Infrastructură” (stare cluster, oprire/pornire cluster, UPS doar simulare, DR VM 109,
|
||
failover/failback backup-uri Oracle cu fișe de instrucțiuni), panouri colapsabile și compacte
|
||
în tot dashboard-ul, `/infra` cu butoane de confirmare. Joburile rulează prin `systemd-run`
|
||
pe noduri. Pornirea: JuiceSSH → 10.0.20.36 → `C:\wolcluster.bat`. Parola UPS mutată în
|
||
`/etc/nut/ups-shutdown.conf`. Scripturile VM 201 se arhivează (VM 201 e în HA).
|
||
- **Mockup aprobat:** https://claude.ai/code/artifact/fa65619b-2310-4d65-9939-ffb1a3f7183b
|
||
- **Verificat:** simulări pe pvemini (oprire, pornire, oprire de urgență UPS ca `nut`), job
|
||
real `systemd-run` prin API (oprire --dry-run, cod 0, fără efecte), stare live, 511 teste,
|
||
`/infra` înregistrat (9 comenzi slash). tmux instalat pe noduri.
|
||
- **Terminat:** 2026-09-13
|
||
|
||
### Maria — reset fire de discuție din dashboard
|
||
- **De unde a pornit:** un test manual în grupul „Maria Test" a rămas legat de
|
||
un fir vechi (Maria trata mesajele ca „firul are eroare X", ancorat pe o
|
||
discuție anterioară) și nu exista nicio cale să-l resetezi fără intervenție
|
||
directă pe server — nici comandă de chat, nici buton.
|
||
- **Ce s-a făcut:** secțiune nouă „Fire de discuție active" în dashboard,
|
||
între „Trimise la suport" și „Clienți cunoscuți": listă cu JID, subiect
|
||
scurtat, ultima activitate, buton de ștergere cu confirmare. Rutele
|
||
`GET /api/maria/fire` și `POST /api/maria/fire/delete` citesc/șterg direct
|
||
fișierele din `~/.maria-bridge/conversations/`, cu aceeași sanitizare de
|
||
nume de fișier ca `rag/fir.py` (oglindă, nu import — coliziune de modul
|
||
`config` între cele două proiecte).
|
||
- **De ce listă și nu un buton fix pe grupul de test:** nu există în cod nicio
|
||
constantă pentru JID-ul grupului de test — apare doar în README. O listă
|
||
acoperă orice fir activ, nu doar unul hardcodat.
|
||
- **Verificat:** 6 teste noi (`test_maria_fire.py`), 11/11 cu cele de clienți;
|
||
fără regresii pe `test_dashboard.py`.
|
||
- **Terminat:** 2026-09-08
|
||
|
||
### Maria — profil de client (firmă), asociat cu mai multe numere
|
||
- **De unde a pornit:** clienții contactează suportul cu întrebări generice
|
||
("am o problemă cu factura") fără context — Maria nu știa că un anumit
|
||
client e, de exemplu, un service auto care lucrează în RoAuto, deci nu
|
||
putea interpreta întrebarea în lumina programului lui.
|
||
- **Ce s-a făcut:** un fișier nou (`rag/client.py` + `~/.maria-bridge/clients.json`)
|
||
ține profiluri de client (nume, notiță text liberă, listă de numere de
|
||
telefon). Un client poate avea mai mulți angajați care scriu de pe numere
|
||
diferite — toți găsesc același profil. La fiecare mesaj, profilul se
|
||
citește de pe disc (stateless, ca restul Mariei) și intră într-o secțiune
|
||
`DESPRE CLIENT` în prompt, înaintea contextului RAG. Administrare prin
|
||
dashboard (`discord-bridge/dashboard`, secțiunea „Clienți cunoscuți"),
|
||
nu prin comandă în chat — canalul de scriere trebuie autentificat.
|
||
- **De ce profilul nu intră în căutare:** pragurile de acoperire din
|
||
`rag/rank.py` sunt calibrate pe textul întrebării; a adăuga cuvinte fixe
|
||
de profil la fiecare interogare ar strica raportul de termeni distincți
|
||
și ar agrava firul deja deschis mai jos ("termenii distinctivi pe
|
||
interogarea combinată"). Profilul filtrează interpretarea răspunsului,
|
||
nu participă la decizia „am/nu am informația".
|
||
- **Mesaje de grup:** dacă cineva scrie într-un grup WhatsApp, se identifică
|
||
persoana din `participant`, nu grupul — altfel grupul s-ar putea potrivi
|
||
accidental cu primul client găsit.
|
||
- **Granița infra:** profilul e strict business (nume firmă, domeniu, program
|
||
ROA folosit) — niciodată date tehnice de instalare (server, parole).
|
||
Precizare adăugată în `CLAUDE.md`, secțiunea „Maria — GRANIȚĂ OBLIGATORIE".
|
||
- **Verificat:** 117 teste (110 existente + 7 noi) în `maria-whatsapp-bridge`,
|
||
plus teste noi pentru rutele de dashboard (`test_maria_clients.py`).
|
||
- **Terminat:** 2026-09-08
|
||
|
||
### Maria — rank hibrid, escaladare la suport, dicționar Oracle
|
||
- **De unde a pornit:** o captură cu o eroare Oracle a primit un răspuns generic — corect
|
||
gramatical, dar despre altă eroare. Nu se putea nici măcar afla ce citise OCR-ul.
|
||
- **Ce s-a făcut:** (1) textul OCR se loghează integral, cu interogarea de căutare și
|
||
sursele alese cu scoruri; (2) ordonare hibridă embeddings + BM25 cu fuziune RRF, și o
|
||
decizie separată „avem acoperire?"; (3) când nu avem, modelul nu mai e întrebat deloc —
|
||
întrebarea pleacă la suport pe WhatsApp, cu captura atașată și o referință; (4) dicționar
|
||
de 29 de erori Oracle uzuale, scris pentru clienți, nu pentru administratori.
|
||
- **De ce hibrid și nu doar embeddings:** măsurat, intervalele se suprapun — întrebările
|
||
bune dau 0,600–0,816 și cele străine 0,534–0,685. Codurile (`ORA-01722`, `D406`, `CIF`)
|
||
sunt exact ce ratează căutarea semantică. Pragurile sunt măsurate cu
|
||
`ops/calibrate-rank.py`, nu alese din burtă: 19/19 pe setul de cazuri.
|
||
- **Două lucruri găsite în log pe drum:** fiecare mesaj din self-chat sosea de două ori
|
||
(pe `@s.whatsapp.net` și pe `@lid`), deci Maria răspundea dublu — dedup pe `key.id`.
|
||
Și reindexarea refăcea toate embeddings-urile (~7 s fiecare): acum refolosește vectorii
|
||
chunk-urilor nemodificate — 29 noi în loc de 169.
|
||
- **Un bug vechi reparat pe parcurs:** documentele adăugate din dashboard ajungeau în
|
||
oglinda Drive și dispăreau la următorul `rclone sync`. Acum există `documents-local/`.
|
||
- **Rămas de făcut:** `SUPPORT_JID` e propriul număr, pentru testare — de schimbat cu
|
||
numărul sau grupul echipei de suport. Dicționarul Oracle trăiește doar pe container;
|
||
locul lui e `document_store` din Drive.
|
||
- **Verificat:** 73 de teste (de la 26 la începutul zilei); o escaladare reală cu captură
|
||
a plecat pe WhatsApp și apare în dashboard.
|
||
- **Terminat:** 2026-08-31
|
||
|
||
### Maria — asociere prin cod de telefon și citirea capturilor cu erori
|
||
- **Ce s-a făcut:** două lucruri cerute în aceeași frază. (1) Asocierea WhatsApp se poate
|
||
face acum și cu un cod de 8 caractere, nu doar cu QR — util când nu ai un ecran de dus în
|
||
fața telefonului. (2) Maria citește capturile de ecran trimise pe WhatsApp: puntea
|
||
descarcă imaginea, `rag/ocr.py` o trece prin tesseract `ron+eng`, restul lanțului rămâne
|
||
neschimbat.
|
||
- **De ce OCR și nu un model vizual:** modelul de răspuns (Qwen3.5-2B pe LXC 104) e strict
|
||
text. Nu e o alegere de calitate, e singura cale fără a schimba modelul.
|
||
- **Blocaje găsite pe drum:** endpoint-ul `/pair` exista, dar după introducerea codului
|
||
WhatsApp cere un restart (515) care consuma din bugetul de reîncercări și putea opri
|
||
puntea la a cincea asociere. Separat, capturile trimise „efemer" ajungeau ca mesaje
|
||
fără conținut și se aruncau tăcut — lipsea despachetarea `ephemeralMessage`.
|
||
- **O decizie care nu se vede din cod:** căutarea în index merge doar pe liniile care arată
|
||
a eroare, nu pe toată captura; un ecran de meniuri și totaluri diluează embedding-ul.
|
||
Modelul primește totuși fereastra întreagă, marcată ca text OCR.
|
||
- **Verificat:** 16 teste noi (suita Maria: 42 pass), OCR real pe o captură cu
|
||
`ORA-01722: invalid number` — extras corect; ambele servicii repornite și conectate.
|
||
- **Terminat:** 2026-08-31
|
||
|
||
### Echo re-legat la WhatsApp după delogare
|
||
- **Ce s-a întâmplat:** puntea WhatsApp a lui Echo (LXC 110) fusese delogată de pe telefon
|
||
dimineața (401). Utilizatorul a eliberat un slot de dispozitiv; puntea a fost re-legată
|
||
prin **cod**, nu prin QR — `auth/` salvat în `auth.bak-2026-08-31`, serviciul repornit,
|
||
`POST /pair`. Acum e dispozitivul `:14` al aceluiași cont.
|
||
- **Ce s-a lămurit:** de ce nu răspund ambele punți în chatul „Eu". Amândouă primesc
|
||
mesajele, dar Echo le aruncă pe toate cu `fromMe && !isGroup`, iar în self-chat tot ce
|
||
scrii e `fromMe`. Echo folosește „Eu" doar ca destinație de notificări. Echilibrul e
|
||
accidental — scris în `romfastsql/docs/chatboti-si-punti.md`.
|
||
- **Terminat:** 2026-08-31
|
||
|
||
### Maria mutată pe LXC 171, cu tot ce s-a construit
|
||
- **Ce s-a făcut:** LXC 171 asociat la WhatsApp (+40723197939, dispozitiv nou al aceluiași
|
||
cont); prototipul de pe LXC 104 oprit și dezactivat. `llama-qwen35` rămâne pe 104 și e
|
||
folosit de 171 prin rețea (`LLM_URL=http://10.0.20.161:8091`).
|
||
- **Rezultat:** Maria a trecut de la 24 de chunk-uri dintr-un singur fișier la 173 din 11
|
||
documente, plus sincronizare Drive automată.
|
||
- **Un blocaj găsit pe drum:** după asociere nu răspundea nimic. WhatsApp livrează
|
||
self-chat-ul cu JID de tip LID (`51947713372214@lid`), iar filtrul compara doar cu
|
||
`<număr>@s.whatsapp.net` — arunca tot, fără nicio urmă în log. Reparat în
|
||
`whatsapp/index.js`; mesajele respinse se loghează acum cu motivul.
|
||
- **Verificat:** „token efactura expirat" → preluat, căutat în RAG, răspuns trimis.
|
||
- **Terminat:** 2026-08-31
|
||
|
||
### Maria — sincronizare Google Drive
|
||
- **Unde:** `maria-whatsapp-bridge/ops/setup-drive.sh`, `rag/sync.py`,
|
||
`docs/rclone-google-drive-headless.md` (în romfastsql)
|
||
- **Ce face:** `rclone` autorizat cu token obținut pe stația Windows (`rclone authorize`,
|
||
fără cont de serviciu Google), dosarul fixat pe ID. `maria-sync.timer` trage la 10 min.
|
||
- **Rezultat:** depozitul a trecut de la 6 la 11 documente — au intrat SAF-T D406,
|
||
e-Factura (`.md` + `.xml`), roaauto și roagest, care lipseau complet.
|
||
- **Terminat:** 2026-08-31
|
||
|
||
### Maria indexează .xml, preferat peste .md
|
||
- **Unde:** `maria-whatsapp-bridge/rag/store.py` (`DOC_EXTENSIONS`,
|
||
`documents_for_index`), `rag/indexer.py` (`chunk_xml`), `rag/sync.py`,
|
||
`discord-bridge/dashboard/api.py` + `index.html`, `tests/`
|
||
- **Ce face:** `.xml` intră în depozit și, când același document există și ca `.md`,
|
||
doar `.xml` se indexează (`.xml` > `.md` > `.txt`); cel umbrit rămâne pe disc și e
|
||
marcat în dashboard. XML-ul se taie câte un chunk per problemă, cu mesajul de eroare
|
||
și rezolvarea împreună.
|
||
- **De ce:** la `d406_saft_knowledge`, `.xml` e cu 3 luni mai nou și cu 50% mai mare
|
||
decât `.md`. Tăierea pe linii goale ar fi separat eroarea de rezolvare.
|
||
- **Verificat:** 20 de teste noi (suita Maria, prima ei suită); puntea Discord 426 pass.
|
||
- **Terminat:** 2026-08-31
|
||
|
||
### Atașamente Discord → Claude (imagini + fișiere text)
|
||
- **Unde:** `romfastsql/proxmox/lxc171-claude-agent/discord-bridge/bot.py`
|
||
(`build_user_content`), `runner.py` (`user_message`), `tests/test_attachments.py`
|
||
- **Ce face:** imaginile png/jpeg/gif/webp ajung ca blocuri `image` (max 4, max 3,5 MB),
|
||
fișierele text intră în prompt (max 4, trunchiate la 100 KB), restul sunt doar numite.
|
||
Merge și mid-tur, ca steering. Un mesaj doar cu poză nu mai e respins ca gol.
|
||
- **Verificat:** 31 de teste noi, suita 426 pass; blocurile de imagine testate pe CLI-ul
|
||
real (`--input-format stream-json`), Claude descrie corect imaginea.
|
||
- **Terminat:** 2026-08-31
|
||
|
||
### Plan cu Opus, execuție cu Sonnet
|
||
- **Unde:** [docs/flux-dezvoltare.md](docs/flux-dezvoltare.md), referit din `CLAUDE.md`
|
||
- **Ce face:** orice cerere de dezvoltare trece întâi printr-un subagent `Plan` pe Opus;
|
||
planul se postează în fir, apoi execuția merge pe Sonnet, în sesiunea firului.
|
||
- **Terminat:** 2026-08-31
|
||
|
||
### Memorie comună claude-agent ↔ romfastsql
|
||
- **Ce face:** `~/.claude/projects/-workspace-claude-agent/memory` e symlink către memoria
|
||
proiectului `romfastsql`, deci firele Discord nu mai pornesc fără context.
|
||
- **Terminat:** 2026-08-31
|
||
|
||
### Repo propriu pentru claude-agent + reparare Gitea
|
||
- **Ce face:** `/workspace/claude-agent` e repo separat
|
||
(`git@gitea.romfast.ro:romfast/claude-agent.git`), scos din `romfast/workspace`.
|
||
Gitlink-urile fără `.gitmodules` care dădeau 500 pe pagina repo-ului `workspace` au
|
||
fost scoase din index.
|
||
- **Terminat:** 2026-08-31
|
||
|
||
---
|
||
|
||
## Jurnal
|
||
|
||
Cea mai recentă intrare prima. O linie per schimbare de stare.
|
||
|
||
- 2026-09-13 — ✅ Infrastructură în dashboard + `/infra` în Discord (oprire/pornire cluster, UPS, DR, failover backup)
|
||
- 2026-09-08 — ✅ Maria: buton de reset pentru firele de discuție active, din dashboard
|
||
- 2026-09-08 — ✅ Maria: profil de client (firmă) asociat cu mai multe numere, injectat în prompt
|
||
- 2026-09-01 — ✅ Maria: mesajul și captura sunt același lucru; cosinusul singur nu mai e dovadă
|
||
- 2026-09-01 — ✅ Maria: „am trimis la suport" doar când puntea chiar a trimis
|
||
- 2026-09-01 — 🔵 Maria: termenii distinctivi pe interogarea combinată (planificat)
|
||
- 2026-08-31 — ✅ Maria: rank hibrid + escaladare la suport + dicționar de erori Oracle
|
||
- 2026-08-31 — ✅ Maria: asociere prin cod de telefon + citirea capturilor cu erori (OCR)
|
||
- 2026-08-31 — ✅ Echo re-legat la WhatsApp prin cod, ca dispozitiv `:14`
|
||
- 2026-08-31 — ✅ Maria mutată pe LXC 171; reparat filtrul care arunca mesajele LID
|
||
- 2026-08-31 — ✅ Maria — sincronizare Google Drive, 6 → 11 documente
|
||
- 2026-08-31 — ✅ Maria indexează .xml, preferat peste .md
|
||
- 2026-08-31 — ✅ Atașamente Discord → Claude (imagini + fișiere text)
|
||
- 2026-08-31 — ✅ Plan cu Opus, execuție cu Sonnet
|
||
- 2026-08-31 — ✅ Memorie comună claude-agent ↔ romfastsql
|
||
- 2026-08-31 — ✅ Repo propriu pentru claude-agent + reparare Gitea
|