Notă metodologică·Monitorul.ai·Arhivă publică
Despre arhivă
monitorul.ai este o arhivă publică și citabilă a stenogramelor parlamentare din România, extrase din Monitorul Oficial al României, Partea a II-a. Această notă explică ce găsești în arhivă, de unde vin datele, de ce link-urile rămân stabile și unde poți semnala erori — întâi pe scurt, apoi cu detalii tehnice pentru cititorii care vor să înțeleagă pipeline-ul, identitatea înregistrărilor și mecanismul de căutare.
Partea I
Pentru toți cititorii
O privire de ansamblu, fără jargon. Dacă citești arhiva ca jurnalist, cetățean, studentă sau cercetător din afara domeniului tehnic, această parte îți este suficientă.
Ce este monitorul.ai
Monitorul.ai este o copie căutabilă a stenogramelor parlamentare publicate oficial. Tot textul de pe site vine din Monitorul Oficial al României, Partea a II-a — registrul în care apar săptămânal ședințele de plen ale Camerei Deputaților, ale Senatului și ședințele comune, sintezele lucrărilor comisiilor parlamentare, interpelările, întrebările scrise și rapoartele instituțiilor care raportează în Parlament.
Diferența față de PDF-ul oficial este că aici poți căuta într-un text — nu doar în titlul documentului — poți să vezi pe profilul unui politician toate intervențiile sale și poți trimite unei colege un link care va deschide aceeași intervenție și peste cinci ani. Stenogramele rămân așa cum au fost publicate; arhiva nu rezumă, nu reformulează și nu adaugă comentariu redacțional.
Site-ul nu este o sursă oficială. Pentru documentul cu efect juridic consultați monitoruloficial.ro. Monitorul.ai este un strat de citare și descoperire peste documentele publice; autoritatea juridică rămâne la sursă.
De unde vin datele
Datele sunt importate automat din PDF-urile publicate pe monitoruloficial.ro. Un program de prelucrare descarcă fiecare număr nou, citește textul stenogramelor, identifică ce intervenție aparține cui, ce vot a urmat după ce, ce raport a fost prezentat în care ședință, și pune totul într-o formă în care poți căuta.
Importul nu adaugă nimic la conținut: nu rezumă, nu reformulează, nu interpretează. Stenograma rămâne așa cum a fost publicată; singura activitate este reorganizarea — ce era într-un PDF de o sută de pagini devine o listă de ședințe, fiecare cu ordinea de zi, intervențiile și voturile.
Procesul tehnic, etapă cu etapă, este descris la Pipeline-ul în opt pași.
Ce găsești și ce nu găsești
Arhiva acoperă Partea a II-a a Monitorului Oficial — actele de cameră: stenograme, sinteze de comisie, întrebări și interpelări, rapoarte instituționale. Nu acoperă Partea I (legi promulgate, decrete, hotărâri de guvern, ordonanțe) și nici celelalte părți. Pentru aceste acte, sursa este tot site-ul oficial.
Anumite documente vechi sau scanate pot avea lacune. Tipic sunt stenogramele dinainte de 2015 cu erori de scanare sau cu inserții corupte: programul le validează ca fiind structural valide, dar lasă fragmente de text care nu apar la căutare. Aceste documente sunt în arhivă fără semnale de alertă; cititorii care observă lipsa unei intervenții pe care o cunosc din altă sursă o pot raporta (vezi Cum semnalezi o eroare).
Profilurile politicienilor sunt completate progresiv. Fiecare politician care a vorbit cel puțin o dată în arhivă are deja o pagină. Datele biografice (mandate, partid, an de naștere) sunt adăugate treptat din surse externe; un profil care arată doar numele canonic, fără mandate atașate, este un profil în curs de completare, nu o eroare ascunsă.
Indexul curent acoperă perioada începând din 2000 și este împrospătat pe măsură ce noi numere ale Monitorului Oficial sunt publicate. Indexarea retroactivă pentru anii 1990–1999 rămâne deschisă; documentele din această perioadă există în formate eterogene și necesită o cohortă separată de testare.
De ce link-urile rămân stabile
Fiecare ședință, fiecare intervenție, fiecare vot are un identificator stabil care nu se schimbă în timp. Un link spre o intervenție pe care îl copiezi astăzi va deschide aceeași intervenție și anul viitor — și peste cinci ani — chiar dacă programul care citește PDF-urile devine mai bun la a separa intervențiile sau dacă numerotarea internă se ajustează.
Acesta este un contract de design, nu o promisiune politicoasă. URL-urile publicate de monitorul.ai sunt construite astfel încât arhiva să poată fi citată în articole, în lucrări de cercetare și pe rețele sociale fără ca legăturile să se rupă în timp. Dacă documentul-sursă mai există în arhivă, link-ul lui rezolvă la aceeași intrare.
Mecanismul prin care se păstrează identitatea — chei stabile minate la importul documentului, o amprentă de conținut care detectează re-organizările și un slug care se generează o singură dată — este descris la Identitatea înregistrărilor.
Cum funcționează căutarea
Caseta de căutare lucrează pe două niveluri în paralel:
- Cuvinte exacteGăsește intervențiile care conțin cuvintele tale. Funcționează cu sau fără diacritice — „sosoaca” găsește intervențiile lui „Șoșoacă”, iar formularea cu diacritice corecte rămâne prioritară.
- Sens apropiatGăsește și intervenții al căror conținut este apropiat de întrebarea ta, chiar dacă nu folosesc exact aceleași cuvinte. Când întrebi „cine a vorbit despre creșterea TVA”, vezi și intervenții care discută același subiect cu termeni diferiți.
Cele două liste sunt combinate într-un singur clasament. Lângă timpul de execuție vezi un cip Hibrid sau BM25 — îți spune dacă a funcționat căutarea pe ambele niveluri sau doar pe primul (cazul tipic: o interogare prea scurtă, o interogare fără rezultate exacte, sau pagini mai adânci în clasament).
Pentru a vedea toate intervențiile unei persoane sau dintr-o ședință, folosește mai degrabă paginile lor decât caseta de căutare — paginile structurate sunt mai precise pentru aceste cazuri.
Detaliile tehnice (BM25, kNN, fuziune RRF, comportamente de degradare) sunt la Hibrid BM25 + kNN.
Ce stocăm despre tine
Site-ul este public și se poate citi fără cont. Atunci când îl citești în browser, NU stocăm cine ești — nicio identitate, nicio adresă de e-mail. Singurul moment în care monitorul.ai îți cere o identitate este conectarea unui asistent AI la serverul MCP, prin autentificare cu Google.
Dacă ai un cont (autentificat cu Google), stocăm doar minimul necesar pentru ca autentificarea să funcționeze și pentru ca limitarea de rată să fie corectă:
- Identitateadresa de e-mail și ID-ul contului Google — necesare pentru ca asistentul tău să te recunoască la următoarea conectare.
- Asistenți conectațilista clienților OAuth pe care i-ai autorizat (Claude Desktop, Cursor etc.), cu numele lor și momentul fiecărei conectări — vizibilă în pagina ta de cont la
/cont, unde poți și revoca oricare dintre ei. - Apeluri MCPatribuim ID-ul tău intern fiecărei cereri spre serverul MCP — nu textul interogării, nu răspunsul, doar "contul X a făcut tool-call-ul Y la ora Z". Folosim asta ca să detectăm și să blocăm abuzul (de exemplu, un singur cont care încearcă să extragă tot corpusul cu cereri scurte).
Nu vindem date, nu rulăm Google Analytics, nu înregistrăm sesiuni și nu profilăm vizitatori. Folosim un singur serviciu de analiză agregată anonimă (PostHog, găzduit în UE), configurat fără cookie-uri și fără identificare individuală — detalii pe pagina de confidențialitate. Ștergerea contului și a tuturor datelor asociate se face la cerere prin canalul de la #corectii. Detalii tehnice (ce coloane stocăm, ce serviciu de bază de date și unde) sunt la Date personale și log.
Cum semnalezi o eroare
Conținutul stenogramelor este reprodus fără modificări. O divergență față de textul publicat în Monitorul Oficial este, prin definiție, o eroare de import și poate fi remediată. Categoriile tipice care apar:
- Atribuire greșităun discurs apare la un alt vorbitor decât cel din original — de regulă o omonimie de nume sau o formă istorică pe care programul nu o recunoaște încă.
- Tăiere greșităo intervenție a fost ruptă în două sau două intervenții consecutive au fost lipite.
- Referințe nelegateun articol citat în text nu este conectat la legea din care face parte.
- Acoperire incompletăun fragment al stenogramei lipsește sau apare amestecat — apare în special pe documente scanate sau cu erori de procesare.
Sesizările se trimit ca issue public în depozitul pipeline-ului, cu link către intrarea afectată din arhivă (URL-ul paginii) și o referință la documentul-sursă (numărul Monitorului Oficial și data ședinței). Permalink-urile fiind stabile, raportul rămâne reproductibil în timp.
Cererile de retragere a unor conținuturi sensibile (de exemplu numele unei părți civile dintr-un dosar care a fost ulterior anonimizat printr-o decizie judecătorească) se gestionează separat: pagina afectată poate fi marcată ca neindexabilă până la rezolvarea sursei. Folosiți același canal pentru aceste cazuri.
Surse și licență
Stenogramele provin din PDF-urile publicate de Regia Autonomă „Monitorul Oficial” pe monitoruloficial.ro. Sunt acte publice oficiale, reproduse aici fără modificări.
Site-urile oficiale ale celor două camere — cdep.ro și senat.ro — rămân autoritatea pentru componența curentă, calendarul ședințelor și textul inițiativelor legislative. Pentru actele cu efect juridic (legi, decrete, hotărâri de guvern, ordonanțe), sursa este Monitorul Oficial Partea I, care nu face obiectul acestei arhive.
Codul-sursă al pipeline-ului este public la github.com/ciocan/monitorul-ii; codul site-ului este public la github.com/ciocan/monitorul.ai. Schemele și mappings-urile sunt versionate alături de cod, deci orice intrare din arhivă poate fi reconstituită din sursă.
Partea a II-a
Detalii tehnice
Pipeline-ul de import, mecanismul de identitate al înregistrărilor și componenta de căutare. Util pentru jurnaliștii de date, cercetătorii și dezvoltatorii care folosesc arhiva ca sursă reproductibilă.
Pipeline-ul în opt pași
Ingestia este realizată de pipeline-ul deschis monitorul-ii, care rulează independent de acest site. Datele trec prin opt etape, fiecare cu răspundere clară și producând un artefact verificabil pe disc:
- FetchDescărcare zilnică a indexului oficial și a PDF-urilor noi. Fiecare PDF este scris atomic și hash-uit (sha256) înainte de a fi marcat ca disponibil.
- ConvertConversie PDF → markdown, cu eliminarea antetelor, paginației și liniilor moi de tăiere a cuvintelor. PDF-urile scanate fără strat text sunt detectate separat și rutate manual prin OCR.
- ClassifyEtichetare după tipul documentului: stenogramă plenară, ședință comună, sinteză de comisie, registru de întrebări scrise, raport instituțional. Detecția folosește semnale din anteturi și din primii 10 KB ai corpului.
- ExtractMarkdown → JSON canonic, cu o schemă strictă per tip de document. Pentru stenograme se decupează ședința, ordinea de zi, fiecare punct, intervențiile, voturile și interpelările. Validarea schemei rulează înainte de scriere.
- LinkTrei pase de legare: rapoartele se atașează la ședința în care au fost prezentate; voturile amânate se leagă de votul care le rezolvă; trimiterile bare la „art. N” se ancorează la cea mai recentă referință explicită din aceeași listă.
- BackfillAsocierea valorilor brute cu registre curate: ministere, instituții care raportează, persoanele din registrul de politicieni. Numele cu diacritice greșite, abrevieri sau forme istorice sunt rezolvate la un identificator canonic.
- EmbedGenerarea vectorilor semantici (BGE-M3, 1024 dimensiuni) pentru fiecare discurs substanțial, titlu de ordine de zi, interpelare și raport. Vectorii sunt fingerprintați față de textul-sursă, deci re-emiterea lor este idempotentă.
- IndexProiectarea sidecar-urilor JSON pe nouă indici Elasticsearch (documente, puncte ale ordinii de zi, discursuri, voturi, interpelări, întrebări, ședințe de comisie, rapoarte, persoane). Acești indici sunt o derivare; sursa de adevăr rămâne pe disc și pe stocarea obiectuală.
Sursa de adevăr este setul de fișiere de pe disc, nu Elasticsearch. Dacă indexul se pierde complet, poate fi reconstruit într-o noapte din sidecar-urile JSON și din artefactele versionate alături. Această proprietate este intenționată: arhiva este construită ca să supraviețuiască infrastructurii care o servește.
Identitatea înregistrărilor
Fiecare înregistrare — un document, un punct al ordinii de zi, un discurs, un vot, o interpelare, o întrebare, o ședință de comisie, un raport, o persoană — primește la extragere un record_id stabil, persistat în sidecar-ul JSON. Identitatea este compozabilă din chei naturale: documentul este mo://YYYY/PART/ISSUE; un punct al ordinii de zi adaugă #agenda-<ord>; un discurs adaugă încă o secvență. Această cheie este preluată direct ca identificator în Elasticsearch și ca bază pentru URL-ul publicat.
Pe lângă identificator, fiecare înregistrare poartă un content fingerprint: un sha256 trunchiat la 12 caractere, calculat peste conținutul normalizat al înregistrării. Fingerprint-ul nu este cheie primară, ci o referință criminalistică: când un extractor este îmbunătățit și granulele se reorganizează, un script de migrare poate spune „vechiul act-12 este același discurs ca noul act-12 (fingerprint coincide) — păstrăm slug-ul publicat”, sau dimpotrivă „vechiul act-12 a dispărut — retragem URL-ul”.
Slug-ul publicat este mintat o singură dată. La re-extragere, dacă record_id rămâne neschimbat, slug-ul anterior este preluat din sidecar-ul de pe disc și păstrat — chiar dacă logica de generare a evoluat. Acest contract slug-once blochează URL-urile publicate împotriva schimbărilor de extractor: o citare făcută în 2025 într-un articol sau pe rețele sociale va rezolva la aceeași înregistrare în 2030, presupunând că documentul-sursă mai există în arhivă.
Identitatea persistată în sidecar este motivul pentru care site-ul, pipeline-ul de îmbogățire (rezumate, NER, codificări de discurs) și jurnalul agentului LLM pot folosi aceleași chei — fără ca fiecare consumator să-și re-implementeze regulile de generare și fără ca derivele să apară în liniște.
Hibrid BM25 + kNN
Căutarea de pe /cauta combină două strategii care răspund la întrebări diferite:
- BM25Potrivire lexicală peste textul discursului, titlul punctului ordinii de zi și numele vorbitorului. Fiecare câmp principal este indexat și într-o variantă „folded”, fără diacritice — astfel căutarea „sosoaca” găsește intervențiile lui „Șoșoacă” via subcâmpurile .folded, iar interogările cu diacritice corecte rămân prioritare.
- kNN semanticVectori BGE-M3 (1024 dimensiuni) pe câmpul „enrichments.embedding”. Întrebări formulate liber — „cine a vorbit despre creșterea TVA”, „discursuri în jurul cazului Caracal” — recuperează intervenții al căror conținut este apropiat semantic, chiar dacă nu folosesc cuvintele exacte din interogare.
Cele două liste de rezultate sunt combinate prin Reciprocal Rank Fusion (constanta standard 60), aplicată pe partea de client al ES, nu prin retrievers nativi — implementarea nativă a RRF în Elasticsearch este sub licență comercială. Modul activ pentru o interogare este afișat ca un cip Hibrid sau BM25 alături de timpul de execuție.
Cazurile în care căutarea rulează doar BM25 sunt explicite: interogarea este goală, serviciul de embedding este momentan inaccesibil, utilizatorul a paginat dincolo de adâncimea în care fuziunea mai are sens (~10 pagini), sau căutarea lexicală a returnat zero rezultate (caz în care o căutare semantică pe termen lipsit de înțeles ar genera potriviri plauzibile dar irelevante). Modul implicit pentru navigarea unui politician sau a unui document este filtrul direct după identitatea înregistrării, nu căutarea — paginile structurate sunt mai precise pentru aceste cazuri.
Date personale și log
Autentificarea pe serverul MCP este implementată prin Better Auth (better-auth) cu plugin-ul mcp: OAuth 2.0 + PKCE + dynamic client registration (DCR), conform RFC-urilor 7591 / 9728 și specificației MCP. Single social provider activ — Google. Token-urile (access ~24 ore, refresh ~30 zile) sunt semnate cu secretul HS256 din variabila de mediu BETTER_AUTH_SECRET.
Backing store: Neon Postgres (proiect monitorul-ai) cu schema:
Atribuția per cerere se face prin câmpul user_id adăugat în fiecare rând al indexului monitorul_query_log. Câmpul rămâne null pentru traficul anonim al site-ului (RSC pages, autocomplete) și conține ID-ul intern Better Auth pentru toate apelurile prin server-ul MCP. Stocăm momentul, tool-call-ul și argumentele — nu rezultatele și nu textul documentelor extrase. Schema completă este în repo: docs/architecture.md.
Bază legală pentru prelucrare: interes legitim (limitarea de rată și diagnoza abuzului serverului MCP) plus consimțământ explicit la momentul autentificării (ecranul de consimțământ /cont/consimt arată numele și URL-ul aplicației înainte de acordare). Drepturile conform GDPR / Regulamentului UE 2016/679 — acces, rectificare, ștergere, portabilitate, restricționare, opoziție — se exercită prin canalul #corectii. Pentru ștergerea contului: deschide un issue în repo cu adresa de e-mail asociată contului; ștergem rândul din user (cascadă spre session, account, oauth_*) și rescriemuser_id la null în log-urile reținute istoric.
Fără cookie-uri terțe, fără pixel de tracking, fără rețele de publicitate, fără session replay. Folosim PostHog (instanță UE-Frankfurt) pentru analiză strict agregată anonimă configurată cookieless (persistence: 'memory', person_profiles: 'never', autocapture: false, disable_session_recording: true). Singurele cookie-uri scrise local sunt cele de sesiune Better Auth (prefix mo.), strict necesare pentru autentificarea OAuth și nevizibile de alte domenii. Detaliile complete despre PostHog (sub-procesor, transferuri, retenție 12 luni, opt-out via Do Not Track) sunt pe pagina de confidențialitate.