Files
rar-autopass/docs/ROADMAP.md
Claude Agent b4818349be docs(5.20): PRD medii RAR per cont (Testare/Productie) aprobat + roadmap
Doua medii RAR configurabile per cont, fiecare cu bifa de activare si set
propriu de credentiale. medii_disponibile=enabled AND creds deriva tot UX-ul.
13 stories / 6 valuri. Premisa verificata live: test/prod = sisteme separate.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-29 19:27:50 +00:00

300 lines
89 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# AutoPass — Roadmap & Proces de Dezvoltare
> **Sursa unica de progres + procesul de lucru.** O sesiune noua are nevoie doar de promptul:
> *"Citeste docs/ROADMAP.md si continua roadmap-ul [optional: livrabila X.Y]."*
> Sesiunea isi detecteaza singura faza (§5.7), planifica SAU executa, verifica si inchide —
> cu doua porti umane: aprobarea PRD-ului si confirmarea commit-ului.
>
> Contractul RAR (sursa de adevar de contract) = `docs/api-rar-contract.md`. Acolo unde un plan
> difera de contract, **contractul are dreptate**.
>
> Status fara emoji (preferinta proiect): **TODO** neinceput · **WIP** in lucru · **DONE** gata ·
> **BLOCAT** blocat de o dependenta · **AMANAT** deferat/taiat cu motiv.
---
## 1. Context
Gateway central care declara prestatiile de service-auto la **RAR AUTOPASS** (Legea 142/2023,
OM 210/2024), portat din clasa Visual FoxPro `RarAutoPass` (ROAAUTO). Stack: **Python/FastAPI +
SQLite (WAL) + httpx + Jinja2/HTMX**. Un container (API) + un proces separat (worker).
Doua canale de intrare, ambele **LIVE pe endpoint-ul de test RAR**:
- **Treapta 1** — canal API (`POST /v1/prezentari`) pentru ROAAUTO / soft propriu.
- **Treapta 2** — import xlsx/csv + mapare coloane + UI web (HTMX) pentru service-uri non-ROA.
---
## 2. Arhitectura (rezumat)
```
Canal API (ROAAUTO) ─┐
Upload web (xlsx/csv) ─┴─▶ Gateway FastAPI ─▶ validare → mapare op→cod → enqueue (PII criptat)
WORKER (proces separat): claim atomic → login RAR → postPrezentare → retry
Dashboard (Jinja2+HTMX) ◀───────┴── monitorizare live RAR + coada + editor mapari + audit CSV
```
Reguli de contract (detalii in `docs/api-rar-contract.md`): `FINALIZATA` e terminal la RAR
(fara anulare/corectie prin API); idempotency = hash de continut server-side; JWT TTL = 30h.
---
## 3. Stadiu Implementare (dashboard)
> **Singurul loc din document care se modifica pe parcurs.** Detaliile NU intra aici — stau in
> PRD-uri (`docs/prd/prd-X.Y-*.md`), linkate in coloana Detalii. La fiecare livrabila terminata:
> schimba statusul + data + linkul PRD si actualizeaza "Ultima actualizare".
**Ultima actualizare**: 2026-06-29 — 5.20 APROBAT (medii RAR per cont: Testare/Productie ca medii configurabile, fiecare cu bifa de activare + set propriu de credentiale). Premisa VERIFICATA live cu 2 seturi reale: test si prod = sisteme RAR complet separate, un set de creds merge pe exact unul (creds dev: test 200/prod 401; creds client real: test 401/prod 200) -> 2 sloturi creds per cont. Model: din `medii_disponibile`=enabled AND creds decurge tot UX-ul (0=blocaj, 1=fara selector/totul acolo, 2=selector import + toggle statusbar + alegere API). Reguli transversale REQ-DISP/VIZ/BADGE/DEFAULT/CONF. Decizii user (toate rezolvate): default API = default cont (NU "test" hardcodat, fiindca clientii sunt prod-only); cont client nou = Productie on/Testare off; confirmare Productie o data la activare (nu per trimitere); `accounts.rar_creds_enc` vechi se STERGE in acest PRD (US-013: ~40 citiri mutate pe per-env + endpoint `POST /v1/conturi/rar-creds` devine env-aware + DROP cu garda assert-copiere, SQLite 3.45). 13 stories / 6 valuri. Idempotenta include `rar_env`; worker sesiuni per `(account_id, rar_env)`; reconciliere pe env-ul submission-ului. PRD: [prd-5.20](prd/prd-5.20-target-rar-test-productie.md). NEIMPLEMENTAT. | ISTORIC: 2026-06-29 — 5.19 PLAN (bifa "Trimite automat la RAR" + coada tinuta/eliberare manuala). PRD prin `/prd` + `/autoplan` (CEO/Design/Eng/DX, voce unica — Codex la plafon pana 2026-07-18). Poarta premise: scop AMBELE (operational + testare), default OFF pastrat "pana devine stabil" (decizie user peste avertismentul de conformitate L.142 -> atenuari OBLIGATORII). Design: per-cont `accounts.auto_send_enabled` (default 0) + per-rand `submissions.held`; snapshot la ingestie la TOATE ~8 situri `status='queued'` printr-un `held_for_account()` (Eng a prins bug real: reactivarea `router.py:237` ocolea Auto OFF); `claim_one AND held=0`; rute web `/auto-send` (toggle, OFF->ON elibereaza in bloc cu confirmare tipata), `/trimite-toate`, `/trimitere/{id}/trimite-acum`. Crescut 6->10 stories: US-007 banner+`/metrics` coada imbatranita, US-008 retentie/purge held (gaura GDPR/L.142), US-009 fixturi teste (id=1 e schema-seeded) + audit, US-010 onestitate API (camp `held` pe `SubmissionResult`+GET, invariant 5.7). 26 taskuri (14 P1). Taste rezolvate cu user: eticheta "Trimite automat la RAR" (coliziune cu "Trimitere automata" worker); testarea sigura (rar_env/`/valideaza`) NEangajata ("doar tinut") -> TODOS. PRD: [prd-5.19](prd/prd-5.19-auto-send-manual-coada.md). NEIMPLEMENTAT. | ISTORIC: 2026-06-29 — 5.18 LIVRAT + VERIFY PASS + CLOSE (corpus k-NN exemple etichetate, pe `feat/5.18-corpus-knn-exemple-etichetate`). Cele 7 stories (US-001..007, inclusiv badge sursa) implementate TDD; seed real **17181 operatii** produs cu subagenti Haiku (blocantul GPU LM Studio rezolvat fara GPU — abatere documentata de la D4, validare Haiku>>Groq la dezacorduri); SILVER populat in productie (era gol); embeddings k-NN pe corpusul etichetat (nu pe cele 18 categorii generice); pre-filtru NUL + precedenta NUL>GOLD>exact>k-NN; badge `confirmat`/`similar`/`non-operatie` pe sugestia fuzzy in editor. VERIFY context curat **1392 passed, 1 deselected (live)** + smoke seeder (17181/NUL=2200/idempotent) + E2E render live badge-uri. `/code-review high` (3 finder x 8 unghiuri): runtime curat, invariant #13 intact, 3 findings cosmetice REPARATE+lock-uite. Commit-uri `756f777`+`308fee6`. PRD: [prd-5.18](prd/prd-5.18-corpus-knn-exemple-etichetate.md). | ISTORIC: 2026-06-29 — 5.16 + 5.17 LIVRAT + VERIFY PASS + COMMIT (`c9f9a1c` pe `feat/5.16-5.17-design-tiers`, nepush-uit). Doua PRD-uri in paralel printr-un agent team (lead orchestreaza, NU scrie cod; teammates Sonnet pe valuri cu fisiere disjuncte; `base.html`/`routes.py`/`_status.html`/`landing.html` serializate ca fisiere fierbinti), 5 valuri / 8 lane-uri: W1-A model 5.17 ∥ W1-B bug-fix chips 5.16 → W2 base.html (fonturi system-stack + scala `--fs-*` + dot RAR + antet ROMFAST + /login brandeit + selector tema + fix Renunta) → W3 enforcement 5.17 ∥ W4-B landing copy ∥ W4-C wizard import → W4-A UI plan → W5 verify. **5.16**: system font stack (zero `@font-face`/`/static/fonts/`, IBM Plex scos — decizie user), scala uniforma in tokeni, contoare separate desktop + bara compacta mobil, antet branded + nume service + badge plan, cele 4 bug-uri chips reparate (picker cod+denumire, add_extra mod operatii, cod ales salvat fara „+", Renunta inchide via `closest`), wizard colapsat + landing Autentificare->/login. **5.17**: `accounts.tier`+`trial_until` (migrare aditiva defensiva) + `app/plans.py` sursa unica (`FREE_MONTHLY_LIMIT=60`, `effective_tier` cu `now` injectabil, `monthly_usage`, `CONSUMED_STATUSES`), trial Pro 30z la creare, CLI `set-tier`, enforcement DUR INAINTE de `build_key` (volum 60 + gate API Pro+, erori 3-niveluri `PLAN_LIMITA_LUNARA`/`PLAN_FARA_API` + `log_event`; `valideaza`/`nomenclator` permise; downgrade lazy; flag `AUTOPASS_ENFORCE_PLANS` kill-switch), UI plan (badge antet + linie burger + consum N/60 + warn>=80% + 6 stari + banner one-time trial->Gratuit + pagina Cont). Regresie autoritara **1380 passed, 0 failed, 1 deselected (live)**; E2E browser real (Playwright 390/1280, logat): /login brandeit, dashboard antet+contoare+dot RAR, burger cu separatoare + RAR + plan. **1 defect prins DOAR de E2E** (invizibil la TestClient): contoare duplicate pe 390px — inline `style="display:flex"` pe `.contoare-desktop` batea `@media` -> mutat in CSS + test-lock. Backend trimitere (worker/masina stari/idempotenta/contract RAR) + `mapping`/`validation` NEATINS. **Igiena commit (decizie user): doar 5.16/5.17** — lucrul paralel 5.18 (corpus kNN: `mapping.py`/`embeddings.py`/`operatii_seed.py`/`tools/mapare-llm/*`/`prd-5.18` + teste corpus, plus `config.py`/`db.py` partial si `conftest.py`/`test_mapare_integrare_l14.py` cuplate) lasat NECOMIS; separare verificata prin worktree izolat la HEAD (booteaza + 69 teste verzi fara niciun fisier 5.18). PRD: [prd-5.16](prd/prd-5.16-tipografie-uniforma-bugfix-editare.md), [prd-5.17](prd/prd-5.17-tipuri-cont-planuri-trial.md). | ISTORIC: 2026-06-28 — 5.16 + 5.17 PLAN: autoplan review rulat in paralel pe ambele PRD-uri (2 agenti Opus; faze CEO/Design/Eng pe 5.16, CEO/Design/Eng/DX pe 5.17), single-voice (Codex la plafon de utilizare pana 2026-07-18, fara consens cross-model). Portile umane inchise cu user: **5.16** User Challenge -> system-ui (scoate IBM Plex self-hostat; risc per-OS + design slop acceptat constient), pre-ship teste Eng E1/E3; **5.17** User Challenge -> enforcement DUR direct de la deploy (CRITICAL GAP migrare legacy = MOOT, pre-productie/fara conturi legacy) + flag `AUTOPASS_ENFORCE_PLANS` optional + 3 taste decisions rezolvate (limita 60 = constanta config; banner one-time trial->Gratuit; `valideaza` dry-run permis pe orice plan). Ambele: 0 decizii deschise, gata de implementare; audit trail + GSTACK REVIEW REPORT scrise in fisierele PRD; niciun commit/push. | ISTORIC: 2026-06-28 — 5.15 + 5.14 IMPLEMENTATE + VERIFY PASS + CLOSE (asteapta confirmare commit). Doua PRD-uri in paralel pe `feat/5.15-propagare-design` (5.15 = propagare design + dashboard editare, 12 stories; 5.14 = mapare LLM distilata, 6 stories). `/code-review high` -> 8 buguri reale reparate TDD (modal rand slim, `/repune` trunchia prestatii, picker chips gol pe re-render, obs re-derivat dupa stergere, GOLD poluat cu cod_op_service, typo `nume_prestatie`, bucketare timp `+3h` gresita iarna -> `localtime`+TZ). Decizie user la CLOSE: **embeddings wire-uit functional** (corpus din nomenclator, gated `AUTOPASS_EMBEDDINGS_ENABLED` default off; era „mort dar scump") + corectie marime model ~50MB->~230MB (estimare PRD gresita). Regresie **1256 passed, 1 deselected (live)**. Backend trimitere (worker/masina stari/idempotenta/contract RAR) NEATINS; embeddings/shared store = suggestion-only (nu intra in enqueue). PRD: [prd-5.15](prd/prd-5.15-propagare-design-dashboard-editare.md), [prd-5.14](prd/prd-5.14-mapare-llm-distilata.md). | ISTORIC: 2026-06-27 — 5.13 IMPLEMENTAT + VERIFY PASS (asteapta confirmare commit). Responsive compact (mobil/tableta) + sistem de butoane + design.md, prin agent team (lead orchestreaza, NU scrie cod; teammates Sonnet pe valuri cu fisiere disjuncte; `base.html` serializat ca fisier fierbinte). Wave 0 BLOCANT (cauza probabila a revert-ului anterior, prinsa de eng review): cele 2 teste responsive feliau ferestre fixe `[idx:idx+5000]` de la PRIMUL `@media (max-width:767px)` -> rescrierea cardului impingea regulile (`min-height:0`/`100vw`) peste fereastra si pica fals; refacut sa ancoreze pe un SENTINEL CSS (`SENTINEL-TESTE-MOBIL`) + slice pana la sfarsitul `<style>` (verificat verde INAINTE de orice CSS). Wave 1 (base.html CSS + `_macros.html` + design.md, paralel): sistem butoane `.btn-secondary/.btn-ghost/.btn-danger/.btn-sm` + `.act/.act-save/.act-del/.act-group` (desktop text / mobil iconita patrata 44px; macro `act_btn(label,ic,kind,attrs)` cu `aria-label` INVARIANT in ramura icon-only + macro `icon()` Lucide stroke save/trash/edit/plus); stepper compact `.stepper-track` (slim >=1024px) / `.stepper-collapsed` ("Pasul N din 4 · Titlu" + bara progres <1024px); FIX P0 break vertical (eliminat `min-width:120px` pe `td::before` care rupea placa B 0 7 5 8" pe verticala -> card stivuit eticheta-deasupra-valorii, checkbox+# ascunse pe mobil = bulk desktop-only by design); cardificare listelor actionabile pana la 1024px (decizie premisa user: O COLOANA, NU 2/rand -> reverseaza Decizie #2 din PRD; zero `grid repeat(2`); versiune ascunsa pe mobil; sticky-bar compacta; `col-actiuni` 92->104 + `.btn-editeaza` nowrap; `design.md` §3/§5.3 aliniate la „o coloana <=1024px"). Wave 2 (`_stepper.html` rescris pe clasele compacte + `_mapari.html` cele 4 butoane icon-only -> `act_btn` + `_submissions.html` guard „Eroare/Eroare" pill-only cand eticheta == stare + linie meta `actualizat` pe card (singurul semnal „blocat?" pe mobil) + `_preview_rand.html` buton editeaza 36px desktop). Wave 3 (teste): `test_web_mapari_actiuni.py` migrat `.icon-btn` -> `.act` (superseda 5.10); 5 teste noi in `test_web_responsive.py` (card fara break 120px, sistem `.act` desktop-text/mobil-icon, `act_btn` aria-label invariant, stepper compact fara anti-patternul 4-coloane, guard „o coloana <=1024px"); fix regresie `test_web_import_stepper.py` (clasa `facut`->`is-done`). Sentinel-ul a fost corectat sa NU contina literal `</style>` (ar fi terminat elementul `<style>` in tokenizer-ul HTML chiar din comentariu -> randare rupta). VERIFY context curat: **992 passed, 1 deselected (live opt-in)** + E2E browser Playwright pe 390/820/1280: mobil 390 carduri compacte fara break vertical (placa orizontala, pill stare, vehicul+VIN, operatie+cod, linie Actualizat), versiune ascunsa, „Eroare" o singura data (guard); tableta 820 O COLOANA (nu 2/rand), header compact pe o linie, fara scroll orizontal; desktop 1280 tabel complet neschimbat (fara regresie), versiune vizibila, checkbox doar pe randuri blocate; wizard desktop = bara slim pe o linie (1 Incarca · 2 Potriveste · 3 Verifica · 4 Confirma) cu ajutor sub. Backend trimitere (worker/masina stari/idempotenta/`build_key`/contract RAR/canal API/`mapping`/`validation`) + schema NEATINSE (pur CSS + markup, `git status`: doar 6 template-uri + design.md + 2 teste). Debt notat (neblocant): „timp relativ" pe linia Actualizat ramane timestamp absolut (backend neatins); SVG Lucide inline pe fiecare rand (sprite `<use>` = optimizare viitoare). PRD: [prd-5.13](prd/prd-5.13-responsive-compact.md). | 2026-06-26 — 5.12 IMPLEMENTAT + VERIFY PASS (asteapta confirmare commit). Editare unificata in modal + cont cu companie/email/CUI obligatorii + rafinari import + responsive tableta/mobil. 8 stories TDD prin agent team (lead orchestreaza, NU scrie cod; teammates Sonnet pe valuri cu fisiere disjuncte; `routes.py` + `base.html` serializate ca fisiere fierbinti). Val 1: US-001 (`accounts.email` migrare defensiva + `create_account` valideaza companie/email/CUI + `account_is_complete` id=1 exceptat + signup CUI obligatoriu + mesaj prietenos CUI duplicat cu `support_email` T3 + CLI `--email`/`--cui`; Q3/D#14 factory in conftest, fara `--allow-incomplete`), US-003 (mapcoloane: cap-tabel coloane + valori prima inregistrare, degradare „antet fara randuri" D#11), US-004 (un singur „Salveaza maparile", ruta plurala `/mapare-operatii`, skip invalid+sumar D#12), US-005 (`_form_editare.html` NOU extras DRY + macro `camp` cu `tip='date'` calendar nativ + degradare ne-ISO gol+hidden raw D#10; `_trimitere_detaliu` consuma, select cod + nemapate raman D#5). Val 2: US-002 (Cont „Date firma" + `POST /cont/date-firma` scoped+CSRF + banner cont incomplet + gate Activeaza pe `account_is_complete`), US-006 (Editeaza preview -> MODAL global `#detaliu-modal-body`, ramura inline `tr.preview-edit` + script mutual-exclusion ELIMINATE, POST editeaza -> `inchideModal`+OOB; R2 submissions neatins). Val 3 (base.html serializat): US-007 (`import_rows.reviewed INTEGER DEFAULT 0` D#7 migrare defensiva; coloana „Verificat?" eliminata -> 8 coloane, VIN nowrap; gate `needs_review` mutat in modal, buton „Confirma valorile" T2 -> `reviewed=1`, banner discoverability T1, gate HARD pe ambele canale D#8, reset reviewed la editare D#9; `reviewed` marcaj separat NU in payload/override/idempotenta), US-008 (`@media` tableta 768-1024 header fara suprapuneri + modal full-screen mobil VERIFICAT D#13, tinte 44px, fara overflow). VERIFY context curat PASS (8/8 stories, dovezi cod+teste; E2E browser Playwright pe 9 scenarii inclusiv responsive 390/820/1280) + 1 FAIL prins si remediat TDD (signup.html eticheta CUI „(optional)" + input fara `required` contrazicea AC US-001 -> `*`+`required`, test lock). `/code-review high` (8 unghiuri subagenti + verificare cod): 3 buguri reale reparate TDD — (1) HIGH `confirma-review` cu `hx-swap="none"` suprima `updateN()` -> `n_confirmat` stale -> commit 422 la prima incercare (aliniat la `hx-swap=innerHTML` ca /editeaza); (2) MEDIUM email duplicat la signup arata mesaj CUI gresit (`"deja folosit"` prindea si eroarea `create_user` -> detectie email-dup intai); (3) MEDIUM a11y butonul Editeaza preview ocolea `open()` (fara inert/focus-trap -> handler global trateaza si `.btn-editeaza`). Debt notat (neblocant): API preview re-deriva needs_review cross-channel, mesaje dead-code camp gol, `zip()` truncheaza POST inegal, id cont in mesaj CUI-dup, duplicari cleanup. Regresie **987 passed, 1 skipped, 0 failed** (baseline 934 -> +53 teste). E2E live RAR `FINALIZATA` neprobat (opt-in indisponibil). Backend trimitere (worker/masina stari/idempotenta/`build_key`/contract RAR/canal API) + `mapping.resolve_prestatii`/`validation.py` NEATINSE (confirmat `git diff --stat`); atingeri schema doar aditive (2 coloane nullable/default, migrare defensiva). PRD: [prd-5.12](prd/prd-5.12-editare-modal-cont-obligatoriu-import.md). | 2026-06-26 — 5.11 LIVRAT (import compact + preview in format Trimiteri + navigatie + simplificare auto_send; dogfooding baza goala). 8 stories TDD prin echipa de teammates Sonnet (lead orchestreaza, NU scrie cod; 6 runde pe valuri cu fisiere disjuncte; `base.html`/`routes.py`/`_coada.html`/`_status.html` serializate). US-001 scoate hold-ul auto_send din mapare (`has_no_auto_send``return False`, simbol pastrat; cod rezolvat→queued; R1 acceptat constient — rastoarna default-ul de siguranta). US-002 scoate bifa auto_send din UI. US-003 preview pas 3 = format Trimiteri (`STARI_PREVIEW`+`nota_umana_preview` in labels.py, fara repr Python/KeyError; view-model `prez`). US-004 filtre layout/stil ca referinta + buton Custom. US-005 nav Trimiteri+Mapari sub contoare pe toate paginile. US-006 import `<details open=are_trimiteri>` nativ. US-007 post-commit reveal (OOB `_coada`+`_status` + `HX-Trigger: trimiteriChanged`). US-008 auto-refresh dupa actiuni (nudge eliminat). VERIFY context curat PASS (8/8 stories, dovezi cod+teste+randare runtime). `/code-review high` (8 unghiuri prin subagenti): 3 buguri reale reparate TDD (#status-bar pierdea tab-ul la self-refresh; pill Custom lasa valori stale; `nota_umana_preview` ascundea "Cod RAR lipsa" pe needs_mapping). Regresie **934 passed, 1 skipped, 0 failed**; smoke boot OK. E2E browser click-through + live RAR `FINALIZATA` neprobate (mediu fara browser/creds). Backend trimitere + schema NEATINSE. PRD: [prd-5.11](prd/prd-5.11-ux-import-compact-preview-navigatie.md). | 2026-06-25 — 5.10 LIVRAT (UX trimiteri: pill filtre + paginare + detaliu; Mapari in meniu; branding ROMFAST + teme). 14 stories TDD prin echipa de workeri (lead orchestreaza, 3 teammates Sonnet pe valuri cu fisiere disjuncte; routes.py si base.html serializate ca fisiere fierbinti). US-001 fix filtrare data (`_iso_date_prefix` pe garda+comparatie). US-002 op service in `payload_view` (chei distincte `op_service_cod/denumire`, conventie goala `""`). US-003 pill-uri categorii `<button>` aria-pressed (needs_mapping `--warn`, needs_data/error `--err`; dropdown status eliminat, lista ID-uri scoasa). US-004 paginare numerotata (total ramificat SQL-COUNT vs fetch-all+slice, clamp page, poll pastreaza pagina via OOB `f-page`). US-005 VIN block-level sub nr. US-006(+US-006b) editare op RAR cu validare nomenclator + recalcul idempotency, pe needs_data/needs_mapping (`/corecteaza`) + error (`/repune`). US-007 op service in detaliu. US-008 eroare simpla in editare (card 3n doar read-only). US-009 Mapari in `#cont-menu` + scoatere tab-bar/`role=tablist` orfan. US-010 pagina Mapari consolidata. US-011 butoane icon SVG + dirty-state (fara kebab/emoji). US-012 header centrat + wordmark `by ROMFAST` (ROM `#D1342F`/FAST `#2E74D6`). US-013 paleta azur ROMFAST (`#2E74D6`/`#1F66C9`) + IBM Plex Sans/Mono self-host (woff2 reale fontsource). US-014 selector tema ciclic Light/Dark/Petrol/Auto + anti-FOUC pe 4 stari. VERIFY context curat PASS (toate 14 stories); `/code-review high`: 1 finding material reparat TDD (US-006b: `error` lipsea din editare op RAR) + 4 minore notate ca debt. Regresie **896 passed, 1 skipped, 0 failed**. E2E browser neprobat (sandbox fara browser interactiv) — recomandat la deploy. Backend trimitere (worker/masina stari/idempotenta/mapping) + schema NEATINSE (UI/UX pur + 1 fix de filtrare). Incident operational: disc 100% plin mid-executie a intrerupt un update npm claude-code (reparat: cache curatat + postinstall re-rulat din staging). PRD: [prd-5.10](prd/prd-5.10-ux-filtre-pill-paginare-mapari-meniu.md). | 2026-06-24 — 5.8 LIVRAT (UX tabel trimiteri + reguli mapare pe text). 11 stories/4 valuri, TDD prin echipa de workeri (lead orchestreaza, nu scrie cod). Reguli text per cont (`operation_text_rules`, substring insensibil diacritice/caz): `resolve_prestatii` capata param aditiv `text_rules` cu precedenta stricta (cod direct > mapare exacta > regula text > nemapat), threadat pe TOATE cele 6 callsite-uri + `valid_codes` + seam `classify_prezentare` (dry-run = trimitere reala); UI Mapari sectiune noua + preview pre-salvare + avertizare overlap + telemetrie `text_rule_hit` in jurnal. UX tabel: `cod_rar` sub operatie, `eticheta_scurta` pill, fara scroll orizontal (scopat `.tabel-trimiteri` + carduri <768px), detaliu INLINE rand-sibling expandabil (chevron+fundal+a11y, pauza poll 15s). VERIFY context curat: **814 passed, 1 skipped** (live opt-in); E2E functional TestClient (browser pixel-level + live RAR neprobate sandbox/login/lipsa creds). **`/code-review high`: 1 bug critic reparat** regula text `auto_send=0` (DEFAULT, decizia CEO siguranta) trimitea automat la RAR in loc sa TINA randul pentru review (`has_no_auto_send` ignora regula text care a rezolvat itemul); reparat TDD + curatare adnotari stale (repara si o telemetrie falsa latenta). Backend trimitere + schema-send NEATINSE (schema pur aditiv). PRD: [prd-5.8](prd/prd-5.8-ux-tabel-trimiteri-reguli-text.md). | 2026-06-24 5.8 PLAN: eng + CEO review rulate (6 decizii incorporate, 11 stories/4 valuri). | 2026-06-23 5.7 LIVRAT (raspuns API onest la blocaje + mapare inline din detaliu). Raportat din client VFP: `POST /v1/prezentari` intorcea `submission_id`+`status` FARA motiv pe randuri blocate (`erori` se popula doar pe ramura `on_unmapped_error=True`) un `needs_data`/`needs_mapping` parea succes ("raspuns fara erori"). Reparat ADITIV: `SubmissionResult` += `nemapate` + `motiv`; `create_prezentari` populeaza `erori` (validare continut, 3 niveluri) / `nemapate` (coduri fara mapare, COD_NEMAPAT) / `motiv` (rezumat uman) pe TOATE caile non-`queued` enqueue, respins (`on_unmapped_error=True`) si reactivare dedup peste `error`. UI: mapare inline in panoul de detaliu trimitere (`POST /trimitere/{id}/mapeaza`, reuse EXACT `save_mapping`+`reresolve_account`, scoped sesiune + CSRF, re-rezolva pe `batch_id`-ul randului deblocheaza si randurile-frate; apare doar pe operatii nemapate reale, nu pe auto_send=0) fara drum prin tab-ul Mapari. `/code-review high`: 2 buguri reale reparate (reactivarea omitea `erori`/`nemapate`/`motiv`; dublu `load_nomenclator` in `_detaliu_ctx`), restul candidatilor infirmati la verify (parse `auto_send` corect via `or ""`; lipsa `conn/account_id` pe ramuri de corectie nereachable cu needs_mapping+unmapped). `pytest -q` **765 passed, 0 failed** (+1 skipped live). **PROBA LIVE `--send` (2026-06-23): mapare inline E2E pe RAR test** `POST /v1/prezentari` cu operatie nemapata `needs_mapping` (raspuns onest cu `nemapate`+`motiv`) mapare inline din panoul de detaliu in browser (Playwright) `queued` worker login RAR + `postPrezentare` `sent idPrezentare=68827`, confirmat independent in finalizate RAR + jurnal `app_events` (`rar_login ok` `submission_sent`). Automatizat ca test live opt-in `tests/test_live_rar.py` (skip implicit; `AUTOPASS_LIVE_RAR=1` + creds test reproduc tot lantul `idPrezentare=68828`). PRD: [prd-5.7](prd/prd-5.7-raspuns-onest-mapare-inline.md). | ISTORIC: FIX out-of-process (raportat din client VFP): `cod_prestatie` necunoscut in nomenclator era trimis raw la RAR **HTTP 500** (`ORA-12899`, coloana `COD_PRESTATIE` max 5 car.) + record PARTIAL `FINALIZATA` (RAR ne-tranzactional) pe care reconcilierea il marca fals `sent`. Reparat: validare `cod_prestatie` fata de nomenclator la ingestie (cod necunoscut tratat ca operatie de mapat, nu se mai trimite raw) + optiune boolean `on_unmapped_error` (`false` default needs_mapping | `true` respinge) per-cerere cu default per-cont `accounts.on_unmapped_error_default` (migrare aditiva). Confirmat live raspunsul RAR (500 pe cod intern vs 200 pe `OE-1`). Inclus si in `c842e33`: fix lease orfan worker (nepotrivire format data sending_since vs cutoff orice rand `sending` parea expirat) + guard anti-dublu-POST + fix UI `hx-confirm` mostenit pe randuri (alerta de stergere la click pe rand). Teste: **748 passed** (cele 2 esecuri pre-existente fara legatura). Contract + CLAUDE.md actualizate. | 5.6 IMPLEMENTAT + VERIFY PASS (asteapta commit). Cele 14 stories din PRD 5.6 livrate TDD (RED->GREEN), `pytest -q` **741 passed, 0 failed**. Lifecycle trimiteri blocate (Val A primul, decizie #18): `app/submissions_admin.py` (sterge/repune scoped, 404-before-409); reactivare dedup peste `error` cu CAS + invalidare sesiune worker la creds noi (T1) + propagare `accounts.rar_creds_enc` (#17) + camp aditiv `reactivated:true` (#19); retentie randuri blocate 30z + `purge_after` curatat la reactivare/requeue (T2); API `DELETE`/`/repune` (200+JSON, #20); UI butoane + bulk + banner "Necesita atentia ta" actionabil cu deep-link. Observabilitate: `app/observ.py log_event` (dublu canal `app_events` DB + `RotatingFileHandler` per-proces, redactare creds/PII la scriere via `app/security.redact_pii`/`vin_partial`), `request_id` middleware + `X-Request-ID` pe toate raspunsurile (T8), handler global excepții -> 500 envelope 6-chei + request_id (T7), audit cerere API (`api_prezentari`/`api_auth_esuat`) + audit worker (`rar_login`/tranzitii), tab "Jurnal" filtrabil scoped (non-admin doar contul sau), retentie jurnal 90z. Live RAR `--send` NEPROBAT in sesiune (recomandat la deploy: confirma `rar_login` ok + `submission_sent` in jurnal). PRD actualizat cu raport VERIFY; contract actualizat cu endpointurile noi (T10). | ISTORIC: HOTFIX livrat + 5.6 APROBAT. Hotfix 500 pe `POST /v1/prezentari` (raportat din client Visual FoxPro): `AUTOPASS_CREDS_KEY` din `.env` nu respecta formatul Fernet (32 bytes url-safe base64) → `ValueError` la primul `encrypt_creds` → 500 brut. Reparat: cheie Fernet valida in `.env` + `crypto.validate_creds_key()` apelata in `main.lifespan` (fail-fast la startup, mesaj clar in loc de 500 la primul POST). Confirmat live: POST VFP → 200 `queued`; trimitere reala pe RAR test → `sent idPrezentare=68818` (verificat independent in finalizate). Corectat si mesajul fals din dashboard pentru starea `error` in `labels.py` ("se reincearca automat" → starea e terminala, NU se reincearca). Investigatia a expus 3 goluri structurale (500 brut fara traducere 3 niveluri; lipsa jurnal de aplicatie la nivel de eveniment; lacune de lifecycle — randuri blocate permanente, dedup blocat de un rand `error`, banner "Necesita atentia ta" neactionabil) → **PRD 5.6 APROBAT** (14 stories; decizii §5 rezolvate cu user). PRD: [prd-5.6](prd/prd-5.6-observabilitate-jurnal.md). | ISTORIC: 5.5 LIVRAT (uniformizare/standardizare UI/UX: tabele la grila Trimiteri, meniu hamburger + tab-bar redus Acasa/Mapari, sterge Ajutor de pe Acasa, panou admin cu selectie+bulk pe model nou `accounts.status`. 9 stories in 3 valuri, UI pur cu o singura exceptie backend = stare cont; stergere soft cu purjare PII imediata GDPR. VERIFY 671 teste + E2E browser (2 bug-uri prinse) + `/code-review high` (2 bug-uri reale reparate). Commit `1fbd894`, vezi randul 5.5). | ISTORIC: 5.4 LIVRAT (Erori pe 3 niveluri problema+cauza+fix pe API si UI: catalog central pur `app/errors.py` ca SINGURA sursa de adevar cod→{problema,fix}, consumat de API+UI+worker — face imposibila divergenta intre canale, acelasi invariant ca 5.2. 8 stories in 5 valuri. Tot ADITIV: `field`/`message`/`error` pastrate la octet, adaugam `cod/problema/cauza/fix`; `rar_error` stocat = SUPERSET (chei vechi intacte → `labels.py` nu se rupe intre valuri, zero migrare). Scope = fluxul de declarare; login/signup/CSRF neatinse. UI progresiv: lista compacta, 3 niveluri complete in detaliu/preview, AA light+dark. VERIFY context curat PASS 628 teste (byte-compat+superset verificate direct, E2E API+web; live RAR neprobat — lipsa creds key). `/code-review high`: 2 bug-uri reale reparate in `labels.py` (`motiv_uman` fara ramura 3-niveluri → 401 creds garbled in coloana Motiv; `parse_erori` element gol pe `{}`). 631 teste. Backend trimitere + schema NEATINSE. PRD: [prd-5.4](prd/prd-5.4-erori-3-niveluri.md)). | ISTORIC: 5.3 LIVRAT (Light/Dark mode: tema light ca bloc `[data-theme="light"]` peste variabilele `:root` — dark NESCHIMBAT la octet; comutator soare/luna in header pe toate paginile, default OS-aware cu fallback dark, persistenta `localStorage` doar la comutare explicita, script anti-FOUC in `<head>` pre-paint; suprafetele de stare hardcodate convertite la `color-mix` in `base.html` + 7 fragmente. Zero backend — pur frontend. VERIFY 2 runde: r1 FAIL a prins literalii dark ramasi in 7 fragmente HTMX (text invizibil in light, test vacuu pe doar base.html) → fix US-003 + test care scaneaza fragmentele; r2 PASS E2E browser (banner light ~13:1 contrast, toggle instant+persista+anti-FOUC, dark identic). `/code-review` high: 1 finding reparat (light `--ok` green sub AA ca text → green-700, ~5.0:1). 584 teste. PRD: [prd-5.3](prd/prd-5.3-light-dark-mode.md)). | ISTORIC: 5.2 LIVRAT (Endpoint dry-run `POST /v1/prezentari/valideaza`: valideaza payload + mapare si intoarce verdictul real — `status_estimat` queued/needs_data/needs_mapping + erori `[{field,message}]` + coduri nemapate + prestatii rezolvate — FARA enqueue, FARA creds, zero scriere DB). 1 story TDD. Cheia de design: helper pur partajat `classify_prezentare` folosit de AMBELE rute, ca dry-run-ul sa nu poata diverge de trimiterea reala (invariant de corectitudine); `create_prezentari` refactorizat pe el cu comportament identic. Scope minim per decizie user: doar validare+mapare (fara idempotency/duplicat, `idempotency.py` neatins), hub `/integrare` amanat ca follow-up (descoperibilitate). VERIFY context curat PASS (577 teste; E2E API cu cele 3 verdicte + COUNT(*)=0 dupa dry-run + fara leak creds in raspuns; regresia de aur verde; live RAR `FINALIZATA` neprobat — lipsa creds key, endpoint read-only nu atinge worker/coada/schema). `/code-review` high: 0 findings (refactor faithful, mutable-default Pydantic-safe, import local necesar anti-circular). PRD: [prd-5.2](prd/prd-5.2-dryrun-valideaza.md). | ISTORIC: 5.1 LIVRAT (Hub de integrare `/integrare`: exemple cod multi-limbaj + retetar VFP cu 2 dialecte + `GET /v1/ping` readiness + export Postman/OpenAPI + "Testeaza conexiunea"). 4 stories in 2 valuri (Val 1 = US-001/US-002/US-004 paralel pe fisiere disjuncte via Agent team; Val 2 = US-003 UI). Atentie operationala: US-003 a rulat intr-un worktree branched din ultimul commit (FARA modificarile necomise ale US-004 din working-tree) si la "copiere manuala" a SUPRASCRIS `routes.py`, stergand ruta `POST /integrare/test-cheie` (8 teste 404) — reparat prin re-aplicarea rutei de catre autorul US-004 pe `routes.py` curent. Lectie: stories care ating acelasi fisier in valuri diferite + worktree = clobber daca worktree-ul nu vede working-tree-ul; foloseste fisiere disjuncte SAU merge atent de catre lead. VERIFY context curat PASS (568 teste) + E2E browser Playwright (deep-link server-side, IA pe 2 niveluri, VFP cu 3 niveluri de tab comuta corect, copy, htmx test-cheie → fragment eroare, 0 erori consola) + enqueue live (`POST /v1/prezentari` → queued); live RAR `FINALIZATA` NEPROBAT in sesiune (lipsa `AUTOPASS_CREDS_KEY`/creds RAR test) — risc minim, backend trimitere NEATINS. `/code-review` high a prins 4 bug-uri reale (toate in suprafata noua, reparate + lock-uite cu teste): snippet C# JSON multi-linie nevalid (CS1010), snippet VFP `json.dumps(indent=0)` inca cu newline-uri → string literal rupt in ambele dialecte, snippet Node `node:buffer` nu exporta FormData → TypeError, script `_integrare.html` ne-scoped acumuland event-listeneri pe tab-bar-ul principal la fiecare swap htmx (scoped pe `#integrare-section`). Notat ca cleanup viitor (nereparat): `_render_integrare` dubleaza SQL `are_creds`/`are_cheie`, `ping` cu 2 conexiuni DB + `account_for_key` de 2 ori, `_campuri_obligatorii` necache-uit, panouri limbaj copy-paste (candidat macro Jinja2). Backend trimitere (worker/masina stari/idempotenta/mapping) si schema NEATINSE. PRD: [prd-5.1](prd/prd-5.1-hub-integrare.md). | ISTORIC: 3.6 INCHIS (editare celule in preview + Acasa unificata). CLOSE: `/code-review` high a prins 1 bug real (decriptare `override_json` neprotejata de try/except in ambele cai de preview — 500 pe tot batch-ul la rotatie cheie Fernet vs. `raw_json` care degrada gratios), reparat in `import_router.preview_import` + `routes._web_compute_preview`; duplicarea `_override_of`/canonicalize notata ca cleanup viitor. 523 teste pass. 7 stories in 3 valuri, executate de 2 echipe in paralel (TeamCreate) pe fisiere disjuncte (core: routes/import/templates; mapari: `_mapari.html`) + US-007 secvential. Livrate: tab "Trimiteri" eliminat→sectiune "Trimiterile tale" sub upload pe Acasa (US-003); upload bara slim accentuata cu hero la first-run (US-004); editare de celule in preview prin `import_rows.override_json` (Approach B, Fernet, patch canonic aplicat ULTIMUL in `_resolve_row_for_preview`+`commit_import` — completeaza inclusiv coloane ABSENTE din fisier), mutatie pura cu status rederivat (US-001); buton Editeaza pe rand cu swap pe `<tr>`+OOB contoare (nu pe sectiune), form propriu, mutual-exclusion, reuse grila `_trimitere_detaliu.html` (US-002); Mapari + formate de coloane ca tabele `.tablewrap`, H4 auto_send stocat (US-005/006); bifa "auto-send"→comutator etichetat pe COADA ("Pune automat in coada"/"Tine pentru verificare"), scoped pe operatie, `name=auto_send` pastrat (zero backend) (US-007). 523 teste pass. **VERIFY**: E2E browser pe `/` (Acasa unificata, upload slim, editare rand needs_data→ok cu swap pe rand + contoare OOB, Mapari tabelar + comutator) + LIVE pe RAR test — import fara coloana data → editarea completeaza data (override) → commit → worker login RAR test → `postPrezentare``sent` cu `idPrezentare=68696`, confirmat independent in lista finalizate RAR. 3 bug-uri JS (htmx 1.9.12) prinse DOAR la E2E in browser (invizibile la TestClient) si reparate: `useTemplateFragments=true` (raspunsul `<tr>`+OOB era parsat in context de tabel → `swapError` + contoare pierdute), re-activare `confirm-btn` deferita pe tick (race `editing=true` tranzitoriu), `n-hint` ok-count actualizat de `updateN`. Backend trimitere (worker, masina stari, idempotenta-logica, mapping-rezolvare) NEATINS — singura atingere de schema: 1 coloana nullable `override_json` cu migrare defensiva. PRD: [prd-3.6](prd/prd-3.6-editare-preview-acasa-unificata.md). | ISTORIC: 3.5 LIVRAT (dashboard compact). 11 stories in 4 valuri, TDD. US-001 bara status compacta pe 2 randuri cu bife accesibile (glife ✓/✗ + text, nu doar culoare) + `format_data_rar` (dd.mm.yyyy hh24:mi:ss, helper pur). US-002 Acasa = ecranul de import (upload dominant inline, tab Import scos, `?tab=import`→Acasa fara 404). US-003 helper pur partajat `app/payload_view.py` (payload→campuri afisabile, defensiv, coercion Excel) refolosit si de `GET /v1/prezentari` (DRY). US-004 "Coada"→"Trimiteri": coloane RO + stare umana + detaliu complet la click in panou dedicat `#trimitere-detaliu` (nu inline — poll 10s), scoped 404 cross-account. US-005/006 CRUD mapari operatii + formate coloane salvate (scoped, re-rezolvare auto la edit cod). US-007 "Mapari" 3 sectiuni (de rezolvat / op salvate / formate coloane), "Cont" doar cheie+creds. US-008 motiv (mesaj validare) pe randuri needs_data in preview. US-009 filtre Trimiteri (stare SQL / vehicul+data Python) scoped + "sterge filtrele". US-010 corectie inline needs_data→queued cu payload+idempotency recalculate, sent read-only (403), coliziune idempotency prinsa pre-UPDATE. US-011 badge contoare pe tab-uri (Mapari/Trimiteri), scoped, aria-label. VERIFY context curat PASS (483 teste; E2E browser/RAR LIVE neprobat — recomandata probare manuala `--send`). `/code-review` high a prins 4 findings reale, toate reparate: corectie needs_mapping re-rezolva prestatiile (nu mai poate trimite cod nul la RAR), filtru fara LIMIT silentios, coliziune idempotency atomica (try/except IntegrityError), comparatie data doar ISO. Backend trimitere (worker, masina stari, idempotenta-logica, mapping-rezolvare, schema) NEATINS. PRD: [prd-3.5](prd/prd-3.5-dashboard-compact-trimiteri-mapari.md). Urmeaza Etapa 4 (4.1 mapare AI/MCP).
> 2026-06-18 — 3.4 LIVRAT (interfata web ergonomica: tab-uri + wizard + microcopy). US-001 modul pur `app/web/labels.py` (stari tehnice→text uman + clasa CSS; test parametrizat din CHECK-ul `schema.sql` iese rosu la stare nemapata). US-002 bara status `/_fragments/status` + `_status.html` (etichete umane, defalcare blocate pe motiv, poll 15s, scoped pe cont). US-003 shell 6 tab-uri (Acasa·Import·Coada·Mapari·Cont·Nomenclator) cu deep-link `?tab=`, panou activ randat server-side, fragmente inactive lazy pe click, ARIA real (tablist/tab/tabpanel + aria-selected + navigare cu sageti). US-004 stepper import 4 pasi (PUR vizual, `hx-target="#import-section"` + csrf pastrate). US-005 Acasa onboarding checklist auto-bifat (are_creds/are_trimiteri) + colaps cand totul gata + empty states prietenoase Coada/Mapari. VERIFY lead-driven (TestClient ACs + 434 pytest pass; E2E browser/RAR LIVE neprobat in sesiune — recomandata probare manuala `--send`). Fix izolare teste (reset `ratelimit._hits` in fixturi, 429 la rulare subset). `/code-review` high: regasit avertisment "cont in asteptare de activare" (regresie din scoaterea `/_fragments/banner`) re-introdus in bara status + culori hardcodate→variabile paleta. 434 teste pass. Backend trimitere neatins. PRD: [prd-3.4](prd/prd-3.4-ux-dashboard-web.md). Urmeaza Etapa 4 (4.1 mapare AI/MCP).
> 3.3b LIVRAT (self-service cheie/creds + admin web + email). US-007 rute web proprii pentru rotire cheie + setare creds RAR scoped pe sesiune (C13, nu endpointul API). US-010 rol admin (`users.is_admin`) + `require_admin`→`AdminRequired`→403 + CLI `tools/account.py set-admin` + bootstrap automat (primul cont care se inregistreaza = admin, citit in `BEGIN IMMEDIATE` anti-race). US-011 panou `/admin` (conturi in asteptare/active, activare/dezactivare cu CSRF + PRG, contul dev id=1 protejat) + link "Panou admin" pe dashboard doar pentru admini + buton logout. US-012 `app/email.py notify_signup` best-effort DEGRADAT fara SMTP (no-op + log, prinde orice exceptie, nu blocheaza signup) + config `smtp_*`. Fix migrare defensiva `users.is_admin`/`email_verified` in `_migrate` (gap prins de VERIFY r1, ca C1 pe `accounts.active`). 2 runde VERIFY context curat (r2 PASS, sweep securitate toate rutele noi sub require_login/require_admin + CSRF, scoped sesiune). `/code-review` high: TOCTOU bootstrap mutat in tranzactie + `_render_admin` extras (anti-duplicare + N+1). 393 teste pass. Urmeaza Etapa 4 (4.1 mapare AI/MCP). Deferat din 3.1 (P3): `rename`/`set-cui`, `--if-not-exists`. SMTP real = follow-up pe US-012.
> 3.3a LIVRAT (self-onboarding web core: `app/users.py` parole scrypt cu eticheta de parametri onorata la verify; `SessionMiddleware` same_site=strict + `app/web/session.py` guard `require_login`→`LoginRequired`; CSRF per-sesiune enforce in prod inclusiv pe login/signup + rate-limit signup & login in-proces; signup `active=0` tranzactie atomica + cheie-o-data + log `SIGNUP`; login/logout; dashboard & import multi-tenant scoped pe sesiune cu regula NULL→cont 1 — toate rutele web care ating date sensibile sub `require_login` + scope; gate worker `claim_one` `LEFT JOIN ... COALESCE(active,1)=1`. 2 runde VERIFY context curat — runda 1 a prins un leak cross-account pe `/_fragments/mapari`, reparat; runda 2 PASS. `/code-review` high a prins 3 findings, reparate. 361 teste pass). Urmeaza 3.3b (self-service cheie/creds + admin web + email). Deferat din 3.1 (P3): `rename`/`set-cui`, `--if-not-exists`.
### Etapa 1 — Canal API ROAAUTO (Treapta 1)
| # | Livrabila | Status | Data | Detalii |
|---|-----------|--------|------|---------|
| 1.1 | Gateway complet: validare + mapare + coada + worker + reconciliere + dashboard | DONE | 2026-06-15 | E2E LIVE prin gateway: `POST /v1/prezentari` → worker → `FINALIZATA` la RAR test (`idPrezentare=68516`). Cod `app/`, 279 teste. |
### Etapa 2 — Import xlsx/csv + UI web (Treapta 2)
| # | Livrabila | Status | Data | Detalii |
|---|-----------|--------|------|---------|
| 2.1 | Parser xlsx/csv 2-treceri + staging criptat (`POST /v1/import`) | DONE | 2026-06 | `app/import_parse.py`; encoding RO, delimiter sniff, coercion, robustete sheet/merged/footer |
| 2.2 | Creds RAR durabile per-cont + worker re-login fallback | DONE | 2026-06 | `accounts.rar_creds_enc`, gate purjare worker |
| 2.3 | `batch_id` scope `reresolve_account` (inchide R1 bulk-send) | DONE | 2026-06 | `app/mapping.py` |
| 2.4 | Mapare coloane + semnatura + detectie drift + fuzzy | DONE | 2026-06 | `app/api/v1/import_router.py` |
| 2.5 | Preview 6 stari + canonicalize partajat + gate HARD + atestare | DONE | 2026-06 | `duplicate_in_file`, `already_sent`, `needs_review`, `import_attestations`, TOCTOU `ON CONFLICT` |
| 2.6 | UI web upload HTMX (drop → mapare → preview → confirma) | DONE | 2026-06 | `app/web/templates/_upload.html`, `_mapcoloane.html`, `_preview_import.html` |
| 2.7 | Export randuri esuate CSV + job purjare `purge_after` + E2E | DONE | 2026-06 | `export_failed_rows`, `tests/test_import_e2e.py` |
### Etapa 3 — Multi-cont / self-onboarding (URMATORUL FOCUS)
| # | Livrabila | Status | Data | Detalii |
|---|-----------|--------|------|---------|
| 3.1 | Creare cont nou (CLI dedicat) | DONE | 2026-06-17 | CLI `tools/account.py` (create/list[--pending]/activate/deactivate, `--with-key` atomic) + `accounts.active` + index unic CUI + `app/accounts.py`. 20 teste noi. PRD: [prd-3.1](prd/prd-3.1-creare-cont.md) |
| 3.2 | Filtrare pe cont a GET-urilor de listare | DONE | 2026-06-17 | scope cheie pe `/v1/prezentari(/{id})`, `/v1/mapari(/pending)`, `/v1/audit/export` (NULL→cont 1); nomenclator global; 404 cross-account identic (B3) + allowlist campuri detaliu (B4) + helper `account_scope_clause` (B2) + index (B5). 14 teste noi, 313 pass. PRD: [prd-3.2](prd/prd-3.2-filtrare-cont-get.md) |
| 3.3a | Self-onboarding web (core) | DONE | 2026-06-17 | `users` (scrypt) + sesiune (`SessionMiddleware`, same_site=strict) + CSRF (enforce prod, inclusiv login/signup) + rate-limit signup/login + signup/login/logout + dashboard & import scoped pe sesiune (NULL→1, anti-leak C6) + gate worker `active=0` (`COALESCE`). 2 runde VERIFY (leak `/_fragments/mapari` prins+reparat) + code-review (csrf erori, scrypt_params, login rate-limit). 361 teste. PRD: [prd-3.3](prd/prd-3.3-self-onboarding-web.md) |
| 3.3b | Self-service cheie/creds + admin web + email | DONE | 2026-06-18 | US-007 (rute web proprii `/cont/roteste-cheie`+`/cont/rar-creds` scoped sesiune, C13), US-010 (rol admin `is_admin` + `require_admin`→403 + CLI `set-admin` + bootstrap primul cont=admin), US-011 (`/admin` activare/dezactivare cu CSRF+PRG, link doar pt admini + logout), US-012 (`app/email.py` notify best-effort degradat fara SMTP + log `SIGNUP`). Fix migrare defensiva `users.is_admin`/`email_verified`. 2 runde VERIFY context curat (r1 a prins migrarea lipsa, reparat; r2 PASS) + `/code-review` high (TOCTOU bootstrap admin mutat in tranzactie + extras `_render_admin` anti-duplicare/N+1). 393 teste. PRD: [prd-3.3](prd/prd-3.3-self-onboarding-web.md) |
| 3.4 | Interfata web ergonomica (tab-uri + wizard + microcopy uman) | DONE | 2026-06-18 | Dashboard reorganizat in 6 tab-uri (Acasa·Import·Coada·Mapari·Cont·Nomenclator) cu deep-link `?tab=` + panou activ server-side + lazy pe rest; bara status cu etichete umane (`app/web/labels.py`) + defalcare blocate; import ca stepper 4 pasi (PUR vizual); Acasa onboarding auto-bifat + empty states. Backend trimitere neatins. 434 teste. PRD: [prd-3.4](prd/prd-3.4-ux-dashboard-web.md) |
| 3.5 | Dashboard compact: import pe prima pagina, status cu bife, Trimiteri lizibile, Mapari complete | DONE | 2026-06-19 | 11 stories (4 valuri), 3 review-uri de plan facute. Acasa=ecran de import (scoate tab Import); bara status compacta font normal + bife accesibile (auto-send/RAR) + data `dd.mm.yyyy hh24:mi:ss`; "Coada"→"Trimiteri" cu coloane RO + detalii comanda din `payload_json` (helper partajat `payload_view.py`) + detaliu la click in panou dedicat; filtrare Trimiteri (US-009); corectie inline `needs_data` cu re-enqueue + detectie coliziune idempotency (US-010); badge contoare pe tab-uri (US-011); "Mapari" 3 sectiuni (de rezolvat / op salvate cu re-rezolvare auto / formate coloane), "Cont"=doar cheie+creds; feedback `needs_data` la import. Backend trimitere neatins. PRD: [prd-3.5](prd/prd-3.5-dashboard-compact-trimiteri-mapari.md) |
| 3.6 | Editare celule in preview + Acasa unificata (Trimiteri inline, upload slim, Mapari tabelar, comutator coada) | DONE | 2026-06-22 | 7 stories (3 valuri), 2 echipe in paralel (TeamCreate) pe fisiere disjuncte + US-007 secvential. US-003/004 tab "Trimiteri" eliminat→sectiune "Trimiterile tale" sub upload pe Acasa; upload bara slim (hero la first-run); `?tab=coada`+`/_fragments/coada`→Acasa; poll gated visibilityState. US-001 `import_rows.override_json` (Approach B, Fernet, `_migrate` defensiv) aplicat ULTIMUL in `_resolve_row_for_preview`+`commit_import` (mutatie pura; completeaza si coloane ABSENTE din fisier); ruta `.../rand/{i}/editeaza` scoped JOIN→404, guard committed→409, empty=clear. US-002 buton Editeaza pe rand, swap pe `<tr>`+OOB contoare (nu pe sectiune), form propriu (confirm dezactivat la editare), mutual-exclusion, reuse grila `_trimitere_detaliu.html`. US-005/006 Mapari/formate tabelar (.tablewrap, H4 auto_send stocat). US-007 bifa auto-send→comutator pe COADA ("Pune automat in coada"/"Tine pentru verificare"), scoped operatie, `name=auto_send` pastrat (zero backend). 523 teste pass. VERIFY E2E browser + LIVE RAR test: import fara coloana data→editare completeaza data (override)→commit→worker login RAR test→`postPrezentare`→sent `idPrezentare=68696` (confirmat in finalizate RAR). 3 bug-uri JS prinse la E2E (invizibile la TestClient) reparate: htmx `useTemplateFragments` (raspuns `<tr>`+OOB parsat in context tabel→swapError), re-activare confirm-btn deferita pe tick, `n-hint` actualizat. `/code-review` high (2026-06-22): 1 bug real reparat — decriptarea `override_json` era in afara `try/except`-ului care protejeaza `raw_json` in ambele cai de preview (`import_router.preview_import` + `routes._web_compute_preview`); la rotatie cheie Fernet / token corupt `raw_json` degrada gratios la `{}` dar `override_json` arunca 500 pe tot batch-ul — acum protejat identic. Notat ca cleanup viitor (nereparat, disciplina backend-neatins): `_override_of` + blocul canonicalize-dupa-override duplicate in 3-4 locuri (preview/commit API vs web). Backend trimitere (worker/masina stari/idempotenta/mapare) NEATINS. PRD: [prd-3.6](prd/prd-3.6-editare-preview-acasa-unificata.md) |
### Etapa 5 — Ergonomie & Integrare (FOCUS CURENT)
> Directie noua (2026-06-22, decizie utilizator): produsul e functional, dar greu de adoptat de
> service-urile care vin din Visual FoxPro / soft propriu. Prioritatea trece pe **usurinta de
> integrare + ergonomie**, peste Etapa 4 (vezi nota de mai jos). Propunere fundamentata cu lentila
> DX gstack (`/devex-review`) pe codul real: lipseste suprafata de onboarding API self-service,
> exemplele de cod, puntea VFP, dry-run-ul si tema light.
| # | Livrabila | Status | Data | Detalii |
|---|-----------|--------|------|---------|
| 5.1 | Hub de integrare (pagina `/integrare` autentificata): exemple cod multi-limbaj (curl/Python/PHP/C#/Node) + retetar **Visual FoxPro** (POST via `MSXML2.ServerXMLHTTP` + upload CSV) + export OpenAPI/Postman + buton "Testeaza conexiunea" | DONE | 2026-06-22 | 4 stories (2 valuri, 2 echipe paralel + restore dupa clobber de merge). US-001 `GET /v1/ping` readiness (`account_id/mediu/autentificat_cu_cheie/are_creds_rar/ts`) + `GET /v1/integrare/postman.json` (v2.1.0, allowlist 3 rute). US-002 `integrare_examples.py` pur (7 limbaje × 2 canale, drift-test `is_required()`). US-003 tab "Integrare" IA pe 2 niveluri (limbaj→canal, VFP cu dialecte MSXML2/WinHttp), copy din `<pre><code>`, empty-state CTA, export `.cardlink`, doar tokens. US-004 `POST /integrare/test-cheie` (`account_for_key` direct, scoped sesiune, no-echo). VERIFY: 568 teste + E2E browser (Playwright: VFP 3 niveluri comuta, htmx test-cheie → fragment eroare, 0 erori consola) + enqueue live; live RAR neprobat (lipsa creds key). `/code-review` high: 4 bug-uri reale reparate (C#/VFP snippet JSON multi-linie nevalid, Node `node:buffer` fara FormData, script ne-scoped acumuland listeneri). Backend trimitere NEATINS. PRD: [prd-5.1](prd/prd-5.1-hub-integrare.md) |
| 5.2 | Endpoint dry-run `POST /v1/prezentari/valideaza` — valideaza payload + mapare, intoarce erorile reale FARA enqueue | DONE | 2026-06-22 | 1 story (US-001), un worker TDD. Helper pur partajat `classify_prezentare` (mapping.py) folosit de AMBELE rute → garanteaza ca dry-run-ul da acelasi verdict ca trimiterea reala (invariant de corectitudine, nu doar DRY); `create_prezentari` refactorizat pe el (comportament identic, test_api.py verde). Ruta read-only: `{results:[{index,valid,status_estimat,erori,nemapate,prestatii_rezolvate}]}`, `rar_credentials` optional+ignorat, zero scriere DB, scope prin `resolve_account_id`. Doar validare+mapare (FARA idempotency/duplicat — decizie user; `idempotency.py` neatins) + hub `/integrare` amanat. VERIFY context curat PASS (577 teste; E2E API: queued/needs_data/needs_mapping + COUNT(*)=0 dupa dry-run, fara leak creds; regresia de aur `POST /v1/prezentari`→queued verde; live RAR neprobat — lipsa `AUTOPASS_CREDS_KEY`/creds test, endpoint read-only nu atinge worker/coada). `/code-review` high: 0 findings. PRD: [prd-5.2](prd/prd-5.2-dryrun-valideaza.md) |
| 5.3 | Light/Dark mode — toggle in header, persistat (localStorage); CSS deja pe variabile `:root` | DONE | 2026-06-22 | 3 stories (US-001 paleta light + US-003 fix suprafete fragmente; US-002 comutator+persistenta+anti-FOUC), un worker TDD secvential (toate ating templates). Tema light = bloc `[data-theme="light"]` care suprascrie variabilele `:root` (dark NESCHIMBAT la octet, default pastrat); fundalurile de stare hardcodate (`#241a1a`/`#201c0f`/`#16241c`) convertite la `color-mix(... 12%, var(--card))` in `base.html` + 7 fragmente `_*.html`. Comutator soare/luna in header (aria-label, >=36px), pe toate paginile (login/signup/dashboard/admin). Default OS-aware (`prefers-color-scheme`, fallback dark); persistenta `localStorage` DOAR la click (init doar sincronizeaza iconita → OS-aware ramane viu pana la comutare explicita); script anti-FOUC in `<head>` inainte de `<style>` (data-theme sincron pre-paint). Zero backend. VERIFY 2 runde context curat: r1 FAIL (literali dark hardcodati in 7 fragmente HTMX → text invizibil in light; testul scana doar base.html, verde vacuu) → fix US-003 (color-mix in fragmente + test care scaneaza `_*.html` de pe disc); r2 PASS (E2E browser: banner light `rgb(246,234,225)`/text `rgb(26,29,36)` ~13:1, toggle instant+persista+anti-FOUC, dark neschimbat). `/code-review` high: 1 finding real reparat (light `--ok` green-600 ~3.3:1 ca text pe alb → green-700 `#15803d` ~5.0:1, trece AA). Backend trimitere NEATINS. PRD: [prd-5.3](prd/prd-5.3-light-dark-mode.md) |
| 5.5 | Uniformizare/standardizare UI/UX: tabele la grila Trimiteri (Mapari compact + toggle Auto/Manual + Ajutor; Nomenclator), meniu hamburger (Cont/Integrare/Nomenclator/Admin/logout) cu tab-bar redus la Acasa+Mapari, sterge Ajutor de pe Acasa, panou admin cu selectie+bulk (Activeaza/Blocheaza/Arhiveaza/Sterge) pe model nou de stare cont | DONE | 2026-06-23 | 9 stories, 3 valuri. UI pur (reskin+reasezare) cu O SINGURA exceptie backend: `accounts.status` (pending/active/blocked/archived/deleted, migrare defensiva, gate worker `claim_one` pastrand `active=1 ⇔ status='active'`). Macro autosend rescris compact pastrand semantica de prezenta `auto_send` (zero backend). Stergere = SOFT: tombstone, dar PII (creds RAR + chei API + CUI) purjate IMEDIAT la stergere (GDPR/L.142), nu prin retentie. VERIFY 671 teste pass (+40); E2E browser Playwright a prins 2 bug-uri invizibile la TestClient (bara bulk `display:flex` inline invingea `[hidden]`; arhivate cadeau sub "in asteptare" → grupare pe status). `/code-review high`: 2 bug-uri reale reparate (soft delete pastra creds+CUI fara purjare → purjare PII la stergere; apostrof in nume rupea `confirm()` inline kebab) + cleanup `_lifecycle_route`. Debt acceptat: `/admin/deactivate`+`set_active` pastrate legacy (test CLI). Backend trimitere neatins (exceptie: gate cont). Commit `1fbd894`. Design: [5.5-uniformizare-ui](design/5.5-uniformizare-ui.md). PRD: [prd-5.5](prd/prd-5.5-uniformizare-ui.md) |
| 5.4 | Erori pe 3 niveluri (problema + cauza + fix) pe API si UI | DONE | 2026-06-22 | Catalog central pur `app/errors.py` (24 coduri, `eroare()``{field,cod,problema,cauza,fix,message}`, ridica pe cod necunoscut) ca SINGURA sursa de adevar, consumat de API+UI+worker (acelasi invariant anti-divergenta ca 5.2). 8 stories, 5 valuri. Tot ADITIV (decizie user): `field`/`message`/`error` pastrate la octet, adaugam 3 niveluri + cod stabil; `rar_error` stocat = SUPERSET (chei vechi intacte → `labels.py` nu se rupe intre valuri, zero migrare). Scope = fluxul de declarare (validare continut, RAR 400/401, import, mapare op→cod); login/signup/CSRF NEATINSE. US-001 catalog; US-002 `validation.py` (cod+3n, byte-compat); US-003 `mapping.py`+`/valideaza` (needs_mapping/auto_send superset, `nemapate` 3n); US-004 worker RAR 400→`RAR_VALIDARE` (field_errors passthrough) + 401→`RAR_CREDS_INVALIDE` (clasificare transient neschimbata, fara echo creds); US-005 `import_router` detalii superset; US-006 `labels.parse_erori` (degradeaza gratios, lectia 3.6) + macro `_eroare.html` (progresiv: lista compacta, 3n complete in detaliu/preview; AA light+dark, accent≠rosu); US-007 upload/mapcoloane web prin macro; US-008 contract documentat. VERIFY context curat PASS (628 teste; byte-compat+superset verificate direct; E2E API `/valideaza` 3 niveluri + regresia de aur queued; E2E web fragmente upload+detaliu; live RAR `FINALIZATA` neprobat — lipsa creds key, endpoint-urile/UI noi nu ating trimiterea). `/code-review high`: 2 bug-uri reale reparate in `labels.py``motiv_uman` nu avea ramura pentru dict-ul 3-niveluri (401 creds → text garbled "field: None; cod:..." in coloana Motiv) + `parse_erori` intorcea element gol pe `{}`/`[{}]` (cutie de eroare goala); cleanup notat ca viitor (dublare `parse_erori`/`motiv_uman`, enrichment COD_NEMAPAT pe 2 straturi, upload handlers copy-paste cross-channel `routes.py`/`import_router`, `json.loads` mort in ramura COLOANE_FORMAT_JSON). 631 teste. Backend trimitere (worker masina stari/idempotenta/mapping-rezolvare) si schema NEATINSE. PRD: [prd-5.4](prd/prd-5.4-erori-3-niveluri.md) |
| 5.6 | Observabilitate & jurnal aplicatie + lifecycle trimiteri blocate: jurnal structurat de evenimente (tabela `app_events` + log text) cu vizualizator in dashboard, handler global 500→eroare 3 niveluri + `request_id`, audit cereri API + login RAR + ciclu trimiteri (worker), redactare PII/creds, retentie/purjare; plus stergere/re-pune in coada randuri blocate (UI+API), dedup care nu mai e blocat de un rand `error`, purjare randuri blocate, banner "Necesita atentia ta" actionabil (link + identificare rand) | APROBAT | 2026-06-23 | Nascut din incidentul 500 (client VFP). HOTFIX deja livrat in afara procesului (US-000): cheie Fernet valida in `.env` + `crypto.validate_creds_key()` fail-fast in `main.lifespan` + mesaj `error` corectat in `labels.py`; confirmat live POST→200, send RAR test→`idPrezentare=68818`. 14 stories ramase: observabilitate US-001..008, lifecycle US-009..013, banner US-014. Decizii §5 rezolvate cu user: retentie jurnal 90z (`AUTOPASS_LOG_RETENTION_DAYS`) + `RotatingFileHandler`; tipuri evenimente extensibile; jurnal non-admin scoped pe cont (admin vede tot); la resubmit doar `error` se re-activeaza (needs_* raman deduped); retentie randuri blocate 30z (`AUTOPASS_BLOCKED_RETENTION_DAYS`); stergere UI cu confirmare simpla + bulk pe lista. NEIMPLEMENTAT inca (doar hotfix-ul e in cod). PRD: [prd-5.6](prd/prd-5.6-observabilitate-jurnal.md) |
| 5.8 | UX tabel trimiteri (detaliu inline, fara scroll, cod RAR sub operatie) + reguli mapare pe text (substring, per cont) | DONE | 2026-06-24 | 11 stories (4 valuri) livrate TDD, executate de echipa de workeri (lead orchestreaza). Reguli text US-001..004 (tabela `operation_text_rules` per cont; `resolve_prestatii` cu param aditiv `text_rules` + precedenta stricta cod-direct>mapare-exacta>regula-text>nemapat; threading pe TOATE cele 6 callsite-uri + `valid_codes` + seam `classify_prezentare`; UI sectiune Mapari cu „contine"/empty state). UX tabel US-005..008 (`cod_rar` in payload_view; `eticheta_scurta` separata; tabel fara scroll orizontal scopat `.tabel-trimiteri` + responsive carduri <768px; detaliu INLINE ca rand-sibling expandabil cu chevron+fundal+a11y+pauza poll 15s via `htmx:beforeRequest`). Expansiuni Val 4 US-009..011 (preview pre-salvare cati nemapate potriveste; telemetrie `text_rule_hit` in `app_events` pe TOATE caile inclusiv corectie+import web; avertizare overlap neblocanta). VERIFY context curat: 814 passed, 1 skipped (live opt-in); E2E functional TestClient (browser pixel-level neprobat sandbox + /login; live RAR neprobat lipsa creds). **`/code-review high`: 1 bug critic real reparat** regula text cu `auto_send=0` (DEFAULT, decizia CEO de siguranta) trecea randul pe `queued` (trimis automat la RAR) in loc sa-l TINA `needs_mapping` pentru review: `has_no_auto_send` inspecta doar `operations_mapping`, nu si regula text care a rezolvat itemul; VERIFY initial ratase cazul. Reparat TDD (`mapping.py`: `_rezolva_din_reguli_text` intoarce auto_send; `resolve_prestatii` marcheaza `regula_fara_autosend` + curata adnotari stale repara si o telemetrie falsa latenta; `has_no_auto_send` prinde flagul). Backend trimitere (worker/masina stari/idempotenta/contract RAR) + schema-send NEATINSE (schema = pur aditiv: tabela noua). PRD: [prd-5.8](prd/prd-5.8-ux-tabel-trimiteri-reguli-text.md) |
| 5.7 | Raspuns API onest la blocaje (`erori`/`nemapate`/`motiv` pe orice status != `queued`) + mapare inline din panoul de detaliu trimitere | DONE | 2026-06-23 | Raportat din client VFP: `POST /v1/prezentari` raspundea `submission_id`+`status` fara motiv pe randuri blocate (`erori` doar pe `on_unmapped_error=True`) `needs_data`/`needs_mapping` parea succes. 3 stories TDD. US-001 (backend API): `SubmissionResult` += `nemapate`+`motiv` (ADITIV), `create_prezentari` populeaza `erori`/`nemapate`/`motiv` pe enqueue + respins + reactivare via helperele `_rezultat_enqueue`/`_rezultat_respins`/`_motiv_clasificare`; `on_unmapped_error=True` pastreaza `erori`=COD_NEMAPAT (compat). US-002 (web): ruta `POST /trimitere/{id}/mapeaza` (reuse EXACT `save_mapping`+`reresolve_account`, scoped sesiune 404 + CSRF, re-rezolva pe `batch_id`-ul randului) + `_nemapate_pentru_submission` + context in `_detaliu_ctx`. US-003 (UI): sectiune "Mapeaza codul operatiei" in `_trimitere_detaliu.html` (selector cod RAR cu sugestie fuzzy preselectata >=60, `ui.autosend_toggle`), doar pe operatii nemapate reale. `/code-review high`: 2 buguri reale reparate (reactivarea omitea `erori`/`nemapate`/`motiv`; dublu `load_nomenclator`), restul infirmate. `pytest -q` **765 passed, 0 failed** (+1 skipped live). **Live RAR `--send` PROBAT (2026-06-23)**: mapare inline in browser → `queued` → worker → `sent idPrezentare=68827` (confirmat independent in finalizate RAR + jurnal `app_events`); automatizat ca test live opt-in `tests/test_live_rar.py` (skip implicit; `AUTOPASS_LIVE_RAR=1` + creds test → reproduce tot lantul, `idPrezentare=68828`). Backend trimitere (worker/masina stari/idempotenta) si schema NEATINSE. PRD: [prd-5.7](prd/prd-5.7-raspuns-onest-mapare-inline.md) |
| 5.10 | UX trimiteri (pill filtre + paginare numerotata + VIN sub nr + editare op RAR + op service in detaliu + eroare simpla) + Mapari in meniu hamburger (pagina consolidata + butoane icon/dirty) + branding ROMFAST (header `by ROMFAST` + paleta azur + IBM Plex + selector tema ciclic Light/Dark/Petrol/Auto) | DONE | 2026-06-25 | 14 stories TDD prin echipa (lead orchestreaza, 3 teammates Sonnet pe valuri cu fisiere disjuncte; `routes.py` + `base.html` serializate). US-001 `_iso_date_prefix` (garda+comparatie, fix filtrare data cu ora). US-002 chei distincte `op_service_cod/denumire` in `payload_view` (conventie goala `""`). US-003 pill-uri `<button>` aria-pressed (needs_mapping `--warn`, needs_data/error `--err`; dropdown status + lista ID-uri eliminate). US-004 paginare numerotata 25/pag (total ramificat: SQL COUNT fara filtru Python / fetch-all+slice cu filtru; clamp page; poll pastreaza pagina via OOB `f-page`; pager ascuns la `pages<=1`). US-005 VIN block-level sub nr. US-006+US-006b editare cod RAR cu validare nomenclator + injectare in `prestatii[0]` + canonicalize + `build_key` (cheie idempotency noua) + check coliziune — pe needs_data/needs_mapping via `/corecteaza`, pe `error` via `/repune` (`error→queued`); read-only pe sent/sending/queued. US-007 op service distinct in detaliu (editabil+read-only). US-008 card eroare 3-niveluri doar pe read-only + rezumat top-of-form pt erori fara camp. US-009 Mapari in `#cont-menu` cu badge + scoatere tab-bar/`role=tablist` orfan/JS sageti. US-010 pagina Mapari consolidata (ordine De rezolvat/salvate/reguli text/formate; ajutor+empty-text scoase). US-011 butoane icon SVG `.icon-btn` mereu vizibile + dirty-state pe `change` (fara kebab/emoji). US-012(+012b) header grid centrat + env badge in grila + logo ROMFAST in header: initial wordmark text, apoi (decizie user) PNG-ul real `/static/romfast_logo.png` (`.brand-logo` ~28px, fundal transparent, lizibil pe toate temele). US-013 paleta azur ROMFAST (`#2E74D6` dark/`#1F66C9` light) + IBM Plex Sans/Mono self-host woff2 (subseturi reale fontsource v5.0.8, latin+latin-ext, `font-display:swap`). US-014 selector tema ciclic Light→Dark→Petrol→Auto + anti-FOUC extins atomic la 4 stari + fallback legacy + `aria-label` curenta+urmatoarea/`aria-live`. VERIFY context curat PASS (toate 14 stories, dovezi in cod). `/code-review high`: 1 finding material reparat TDD (US-006b — `error` lipsea din editarea op RAR, cerut de AC) + 4 minore notate ca debt (comparatie data bruta sigura prin UI; dublu `load_nomenclator` cand nomenclator gol; `vehicul` uppercased in linkuri pager cosmetic; duplicare cale validare+idempotency intre `post_corectie`/`post_repune`). Regresie **896 passed, 1 skipped, 0 failed**. E2E browser NEPROBAT (sandbox fara browser interactiv) — recomandat la deploy (`./start.sh test both --send` + browser pe `/`). Backend trimitere (worker/masina stari/idempotenta/mapping) + schema NEATINSE (UI/UX pur + fix filtrare). Design: [DESIGN.md](../DESIGN.md). PRD: [prd-5.10](prd/prd-5.10-ux-filtre-pill-paginare-mapari-meniu.md) |
| 5.11 | Import compact + preview in format Trimiteri + navigatie + simplificare auto_send (dogfooding baza goala) | DONE | 2026-06-26 | 8 stories TDD prin echipa de teammates Sonnet (lead orchestreaza, NU scrie cod; 6 runde pe valuri cu fisiere disjuncte; `base.html`/`routes.py`/`_coada.html`/`_status.html` serializate ca fisiere fierbinti). US-001 scoate hold-ul auto_send din mapare: `has_no_auto_send``return False` (NEUTRALIZAT, simbol pastrat — importat in routes.py+import_router.py; stergerea ar da ImportError la boot), ramura AUTO_SEND_OPRIT scoasa din classify, cod rezolvat→`queued`, `needs_mapping` doar pt cod RAR nerezolvat; coloane DB raman (default 1, ne-citite); teste vechi rescrise; canal API auto_send=0→queued (R1 acceptat constient: rastoarna default-ul de siguranta CEO). US-002 scoate bifa auto_send din UI (macro golit, 0 reziduuri in 3 sabloane). US-003 preview pas 3 = format Trimiteri (`STARI_PREVIEW`+`nota_umana_preview` in labels.py — fara KeyError pe stari preview, fara repr Python in Note; view-model `prez` din payload_view; `.tabel-trimiteri`+`col-*`+`data-eticheta`+editor `tr.preview-edit` care scapa grila fixa). US-004 rand filtre ca referinta (quick-pills data STANGA+Custom / cautare / pills stare DREAPTA; reset=accent, categorie=culoarea ei; hover color-mix; :focus-visible pastrat). US-005 nav Trimiteri+Mapari sub contoare pe toate paginile (`_status.html`+stub `dashboard.html`, `tab_activ` explicit pastrat la self-refresh, badge sursa unica, logo+titlu link `/`, hamburger Trimiteri-first). US-006 import = `<details open=are_trimiteri>` nativ (colapsat la returning, deschis la first-run, fara toggle JS). US-007 post-commit reveal: `web_confirma_import`→OOB `_coada` (#trimiteri-section)+OOB `_status` (#status-bar)+header `HX-Trigger: trimiteriChanged`, mesaj onest. US-008 auto-refresh dupa actiuni (poller→`reincarcaTrimiteri()` pastrand filtru+pagina; nudge "Date noi" eliminat). VERIFY context curat PASS (8/8 stories cu dovezi cod+teste+randare runtime — verificatorul a pornit aplicatia reala si a inspectat HTML-ul). `/code-review high` (8 unghiuri prin subagenti): 3 buguri reale reparate TDD — (1) #status-bar pierdea tab-ul activ la self-refresh (`_status.html` hx-get fara `?tab=`→nav marca gresit Trimiteri pe ?tab=mapari), (2) pill Custom lasa valori stale→interval inversat silentios, (3) `nota_umana_preview` afisa flag inaintea "Cod RAR lipsa" pe needs_mapping; debt acceptat notat (dublu-fetch idempotent la commit; etichete in 3 locuri; import mort `has_no_auto_send`). Regresie **934 passed, 1 skipped, 0 failed**; smoke boot OK. E2E browser click-through complet + live RAR `FINALIZATA` NEPROBATE (mediu fara browser interactiv/creds web) — backend trimitere (worker/masina stari/idempotenta/`build_key`/contract RAR) si schema NEATINSE (non-goals respectate). PRD: [prd-5.11](prd/prd-5.11-ux-import-compact-preview-navigatie.md). | Bug-uri/frictiuni confirmate E2E (Playwright, prima utilizare): (1) dupa primul import ramai blocat — wizard reset la pas 1, mesaj „vezi mai jos in Trimiterile tale" pointeaza la `trimiteri-section` ABSENT in DOM la first-run, lista nu apare fara reload; (2) navigatie infundata — din Mapari/Jurnal/Cont/etc. niciun link inapoi la Trimiteri, logo ne-link, hamburger fara „Trimiteri"; (3) preview pas 3 — overflow taie Verificat?/Actiuni + formularul de editare, „Note" scapa repr Python brut (`[{'cod_op_service':...}]`), „Stare" coduri brute; (4) `auto_send=0` produce stare falsa `needs_mapping` cu mesaj tehnic fara actiune; (5) filtre neuniforme (pill outline vs buton solid, in dreapta, hover rosu ilizibil); (6) wizard ocupa tot ecranul. 8 stories (3 valuri). Decizii user 2026-06-26 (AskUserQuestion + preview imagini): Q1 filtre = layout complet ca referinta `image.png` + fix hover lizibil; Q2 preview = format ca tabelul Trimiteri; Q3 = **scoatem complet bifa auto_send** (Mapari+Trimiteri); Q4 = acordeon compact + lista apare/refresh automat dupa commit + link-uri Trimiteri/Mapari sub contoare. Backend trimitere NEATINS; singura atingere de logica = `mapping.py` nu mai tine randuri pe auto_send (R1 acceptat: rastoarna default-ul de siguranta). PRD: [prd-5.11](prd/prd-5.11-ux-import-compact-preview-navigatie.md) |
| 5.13 | Responsive compact (mobil/tableta) + sistem de butoane (`.act`/`.btn-*` desktop text / mobil iconita Lucide 44px) + stepper compact + `design.md` (sursa de adevar design) | DONE | 2026-06-27 | Nascut din dogfooding (screenshot-uri urate pe ecrane mici) + eng/CEO/design review (autoplan). Decizie premisa user: listele actionabile = O COLOANA pana la 1024px (reverseaza grila 2/rand). Wave 0 BLOCANT: refacut cele 2 teste responsive fragile (fereastra fixa `[idx:idx+5000]` -> ancora pe SENTINEL CSS + slice la `</style>`), cauza probabila a revert-ului anterior. Wave 1: FIX P0 break vertical (`min-width:120px` eliminat -> card stivuit), sistem butoane `.btn-secondary/.btn-ghost/.btn-danger/.btn-sm` + `.act/.act-save/.act-del` + macro `act_btn` (aria-label invariant) + `icon()` Lucide, stepper `.stepper-track`/`.stepper-collapsed`, cardificare <=1024px (zero `repeat(2`), versiune ascunsa mobil, sticky-bar compacta. Wave 2: `_stepper.html` rescris, `_mapari.html` icon-btn->act_btn (4 butoane), `_submissions.html` guard „Eroare/Eroare" pill-only + linie meta `actualizat`. Wave 3: `test_web_mapari_actiuni.py` -> `.act` (superseda 5.10) + 5 teste responsive noi + fix `test_web_import_stepper.py` (`facut`->`is-done`). VERIFY context curat: **992 passed, 1 deselected (live)** + E2E browser Playwright 390/820/1280 (mobil fara break vertical, tableta o coloana, desktop tabel neschimbat, wizard slim pe o linie). Bulk-select declarat desktop-only by design (checkbox ascuns mobil). Backend trimitere + schema NEATINSE (pur CSS + markup: 6 template-uri + design.md + 2 teste). Debt: timp relativ ramane absolut; SVG inline (sprite = optimizare viitoare). PRD: [prd-5.13](prd/prd-5.13-responsive-compact.md) |
| 5.12 | Editare unificata in modal (preview = acelasi formular ca Trimiteri, scoate editarea inline rupta + eroarea htmx `htmx-internal-data`) + calendar `<input type=date>` pe data prestatiei + cont cu companie/email/CUI obligatorii (`accounts.email` + gate activare) + mapare cu antet+prima inregistrare + un singur Salveaza pe operatii + preview compact fara coloana „Verificat?" + responsive tableta/mobil (header fara suprapuneri) | TODO | | Nascut din dogfooding first-run E2E (Playwright pe `exemple/prezentari_test.csv`, 2026-06-26): reprodus modul de editare inline colapsat pe verticala (`tr.preview-edit` in `table-layout:fixed`) + `TypeError htmx-internal-data` la Anuleaza; data prestatie doar text; toate conturile cu `cui=NULL` + conturi CLI/teste fara email; mapare coloane fara cap de tabel/valori; N butoane Salveaza pe operatii; coloana „Verificat?" neclara; pe tableta/mobil header-ul se suprapune (grila desktop fara breakpoint 7681024). 8 stories (3 valuri). Decizii user (AskUserQuestion 2026-06-26): calendar = `<input type=date>` nativ; email canonic pe `accounts` (model A); coloana „Verificat?" scoasa (gate `needs_review` mutat in modal). Backend trimitere NEATINS; singura schema = `accounts.email` (migrare defensiva). PRD: [prd-5.12](prd/prd-5.12-editare-modal-cont-obligatoriu-import.md) |
| 5.15 | Propagare design landing in aplicatie + dashboard editare (teme aditive, componente slim, dashboard contoare + strip sanatate, lista slim, form editare slim cu chips prestatii multi-cod, obs editabil, bulk-fix, salvare mapare din chip, account-scope pe GET-urile de listare, analytics device-mix) | DONE | 2026-06-28 | 12 stories, verify-pass, prin agent team (lead orchestreaza, teammates Sonnet, TDD per story, `base.html`+`routes.py` serializate ca fisiere fierbinti). US-004 lista slim (`trimitere-slim`), US-006 prestatii multi-cod (`form.getlist` pozitional), US-007 form editare slim + chips + obs, US-009 salvare mapare din chip, US-011 account-scope pe fragmentele de listare (404-before-leak pe id strain), US-012 analytics device-mix fara PII. **CLOSE (`/code-review high` -> reparare TDD 2026-06-28):** 8 buguri reale reparate — (1) HIGH modalul nu se deschidea pe randul slim (`base.html` verifica doar `trimitere-row`, nu `trimitere-slim`, in click+keyboard handler); (2) HIGH `/repune` trunchia prestatii (itera `enumerate(codes)`=1 select -> pierdea prestatii[1:] -> declaratie incompleta la RAR ireversibil; fix: iterare peste `existing`, codes pozitional); (3) HIGH picker chips GOL pe re-render dupa eroare validare/coliziune (`_detaliu_ctx` fara `conn`/`account_id` -> `nomenclator_rar=[]`; fix pe toate 4 ramurile post_corectie); (4) MED obs re-derivat dupa stergere explicita (`_merge_override` pop pe obs -> derive-on-empty il reinvia; fix: pastreaza obs='' explicit); (5) MED mapare salvata fara denumire poluă GOLD partajat cu cod_op_service ca cheie (fix: helper `_record_gold_validation` care sare scrierea cand denumire lipseste/==cod_op_service, aplicat la toate 4 callsite-urile); (6) MED typo `nome_prestatie`->`nume_prestatie` in select /repune; (7) MED bucketare timp `+3 hours` fix gresita iarna (RO=UTC+2 EET; fix: SQLite `localtime` DST-aware + `TZ=Europe/Bucharest` in Docker/compose + tzdata); cleanup: hoist `load_*` din bucla bulk-fix, `import re` la top. Regresie **1256 passed, 1 deselected (live)**. E2E browser real OPEN (Playwright indisponibil in sandbox). PRD: [prd-5.15](prd/prd-5.15-propagare-design-dashboard-editare.md) |
| 5.14 | Mapare LLM distilata: etichetator offline (OpenRouter NVIDIA) + temporal holdout + shared store GOLD partajat cross-account (suggestion-only) + SILVER LLM + embeddings in-proces (fastembed/ONNX) + held-out eval + integrare Layer 2/3 in editor | DONE | 2026-06-28 | 6 stories (S1-S6), verify-pass, in paralel cu 5.15 pe acelasi branch (piese disjuncte de fisier rulate paralel; integrarea L14-S6 in editor venita DUPA 5.15, suggestion-only, fara a atinge designul, D9). Auto-send DOAR GOLD propriu; SILVER/GOLD-partajat/embeddings = sugestie, niciodata auto-send (#11/#13, `resolve_prestatii`/`load_mapping` nu citesc tabelele de sugestii). Gate holdout = SLABA (validare temporala imposibila — CSV fara timestamp; non-blocant). **CLOSE (`/code-review high` 2026-06-28):** bug embeddings „mort dar scump" reparat — `enrich_suggestions` apela `is_available()` neconditionat -> lazy-load model ~230MB sincron in thread-ul de cerere desi corpus gol (`index_corpus` nu era wired) -> zero beneficiu. **Decizie user CLOSE: WIRE embeddings functional** (PRD #15: embeddings in v1): `ensure_embeddings_corpus(conn)` construieste corpus din nomenclator, gated pe `AUTOPASS_EMBEDDINGS_ENABLED` (default OFF -> /mapari instant + teste rapide; ON -> lazy-load la prima cerere, re-index pe semnatura nomenclator); `enrich_suggestions` ramane query ieftin cu garda `has_corpus()`. Corectata marimea modelului in PRD/cod: ~50MB (estimare gresita) -> ~230MB real masurat (`paraphrase-multilingual-MiniLM-L12-v2` ONNX quantizat). Regresie **1256 passed**. PRD: [prd-5.14](prd/prd-5.14-mapare-llm-distilata.md) |
| 5.16 | Tipografie uniforma (system-ui, scoate IBM Plex self-hostat) + scala tipografica uniforma + rebrand antet/login profesional + bug-fix formular editare (4 bug-uri reale) + E2E | TODO | | PRD draft + autoplan (CEO/Design/Eng; DX skip — UI operator) rulat 2026-06-28, single-voice (Codex la plafon de utilizare pana 2026-07-18). **User Challenge #1 REZOLVAT = system-ui** (decizia user; challenge respins, Approach A/IBM Plex picat; risc randare per-OS + design slop #11 „system-ui ca font primar" = ACCEPTAT CONSTIENT). Cele 4 bug-uri confirmate in cod: US-007 (`base.html` `hasAttribute` la buton cu copii -> click pe text nu inchide), US-006 (`post_corectie` nu citeste `chips_add_cod_flat` -> save no-op), US-004 (picker plat doar cod vs op-mode cod+denumire), US-005 (`add_extra` lipseste din `post_form_chips`). Pre-ship (Eng `issues_open`, 0 critical gaps): test E1 (grep literale `IBM Plex` ramase fara fallback) + E3 (by-index op corecta). Audit trail + GSTACK REVIEW REPORT scrise in PRD; niciun commit. PRD: [prd-5.16](prd/prd-5.16-tipografie-uniforma-bugfix-editare.md) |
| 5.17 | Tipuri de cont (free/standard/pro/premium, sursa unica `app/plans.py`) + trial Pro 30 zile automat la creare + enforcement DUR (volum 60/luna Gratuit pe ambele canale + gate API Pro+) + downgrade lazy la expirare + alocare manuala admin (CLI set-tier). Fara billing self-service (non-goal) | TODO | | PRD draft + autoplan (CEO/Design/Eng/DX) rulat 2026-06-28, single-voice (Codex la plafon pana 2026-07-18). **User Challenge REZOLVAT = enforcement DUR direct de la deploy** (decizia user); **CRITICAL GAP „migrare conturi legacy" = MOOT** (fara conturi legacy, pre-productie/in teste). Feature-flag `AUTOPASS_ENFORCE_PLANS` = OPTIONAL (kill-switch de operare, nu blocant). 3 taste decisions rezolvate cu user (toate pe recomandare): limita 60 = constanta config tunabila (sursa unica); banner one-time la trecerea trial->Gratuit; `valideaza` dry-run ramane permis pe orice plan. Limita Gratuit scade 100->60/luna. 0 decizii deschise, gata de implementare. Audit trail + GSTACK REVIEW REPORT scrise in PRD; niciun commit. PRD: [prd-5.17](prd/prd-5.17-tipuri-cont-planuri-trial.md) |
| 5.18 | Corpus k-NN din exemple reale etichetate (mapare operatii): pre-filtru determinist NUL + etichetator offline multi-backend + generator seed pe frecventa + seeder `mapping_suggestions` (SILVER populat in productie) + embeddings indexeaza corpusul etichetat (nu nomenclatorul) + `enrich_suggestions` = NUL > GOLD > exact > k-NN + badge sursa in editor (US-007). Suggestion-only (#13), zero LLM la runtime | DONE | 2026-06-29 | 7 stories (US-001..007) TDD. **Seed real produs cu subagenti Haiku** (decizie user 2026-06-29 — abatere documentata de la D4/LM Studio: GPU box jos; Haiku = motor mai bun, validare 157 op Haiku ~22/30 corect vs Groq ~0 la dezacorduri): `app/data/operatii-etichetate.json` rescris 3758 (Groq partial) -> **17181 operatii distincte** (`source="haiku_seed"`, ordine frecventa, NUL=2200). Seeder `init_db` INSERT OR IGNORE idempotent; embeddings k-NN pe `denumire_normalizata` (query normalizat simetric, F1); precedenta NUL>GOLD>exact>k-NN cu abtinere sub prag. US-007 badge `confirmat`/`similar`/`non-operatie` pe sugestia fuzzy (cerere user la CLOSE). **VERIFY context curat PASS**: suita **1392 passed, 1 deselected (live)**; smoke `init_db` seed=17181/NUL=2200/idempotent; toate codurile in nomenclator (zero cod gunoi -> zero risc HTTP 500/ORA-12899); E2E render live al badge-urilor (confirmat/similar/non-operatie). **CLOSE `/code-review high`** (main..HEAD, 3 finder x 8 unghiuri): calea runtime curata, invariant #13 intact; 3 findings low/cosmetic REPARATE + lock-uite (FD leak tool offline -> `with open`; `cod` whitespace -> NULL in `seed_suggestions` + test; docstring embeddings). Config: `seed_operatii_enabled=True` + `embeddings_enabled=True` default (ambele suggestion-only, dezactivabile prin env; embeddings lazy-load ~230MB la prima cerere /mapari). Commit-uri `756f777` (core+seed) + `308fee6` (fix lateral start-test ONNX). Calitate seed la scara ~95%; coduri rare (avarii grave) sparse, ne-verificate uman -> ramane recomandarea esantion uman (Decision #19) inainte de orice auto-send. PRD: [prd-5.18](prd/prd-5.18-corpus-knn-exemple-etichetate.md) |
### Etapa 4 — Deprioritizat (post Etapa 5, daca apare nevoia din uz real)
| # | Livrabila | Status | Data | Detalii |
|---|-----------|--------|------|---------|
| 4.1 | Mapare AI / conector MCP (sugestie peste fuzzy) | AMANAT | | deprioritizat 2026-06-22 in favoarea ergonomiei/integrarii (Etapa 5) |
| 4.2 | Editare/anulare prezentari trimise | BLOCAT | | `FINALIZATA` terminal la RAR — fara flux API; corectia = suport RAR |
### Amanat / taiat (cu motiv)
| Livrabila | Status | Motiv |
|-----------|--------|-------|
| Drop-fisier SFTP / email-to-import | AMANAT | Valideaza intai upload-ul manual (wedge-ul real), apoi re-evalueaza |
| Contor volum + prag freemium | AMANAT | Metrici de pret inainte sa existe useri; trivial de adaugat post-validare |
| Billing complet (Stripe etc.) | AMANAT | Dupa validarea pragului de volum |
---
## 4. Open questions / riscuri acceptate
- **Un cont = un agent RAR sau mai multi** — afecteaza maparea creds in UI + filtrarea monitorizarii.
Relevant pentru Etapa 3.
- **Valori reale `sistemReparat`** — azi se trimite `"null"`; ce alte valori accepta RAR ramane de probat.
- **R4 (acceptat constient):** creds RAR durabile-at-rest (Treapta 2) → la scurgerea cheii Fernet toate
parolele sunt decriptabile (vs. doar in-flight pe canalul API). Mitigare: rotatie cheie + redactare loguri.
---
## 5. Proces de implementare
### 5.1 Principii
1. **PLAN separat de EXECUTE/VERIFY, pe sesiuni distincte.** Planificarea consuma mult context
(model puternic) si produce **PRD-ul** ca artefact de predare. Executia reia intr-o **sesiune noua**
bazat doar pe PRD — nu pe transcriptul planificarii. **Starea persista in PRD**, nu in conversatie.
2. **TDD ca contract:** testul scris ÎNAINTE = forma executabila a criteriilor de acceptare. Un worker
cu test rosu clar nu poate declara fals victoria — testul decide.
3. **Story atomic = unitate de paralelizare SI de rollback:** un story = un commit logic = un worker =
un test-suite verde.
4. **VERIFY in context curat:** un subagent dedicat care primeste DOAR PRD-ul + instructiunile §5.6,
NU transcriptul executiei (altfel mosteneste partinirea de confirmare a celui care a implementat).
5. **Single writer:** doar sesiunea lead scrie in PRD, ROADMAP si git. Workerii scriu doar cod si teste.
6. **E2E pe canalul real:** un flux se verifica prin canalul lui (upload web prin browser, API prin
`POST /v1/prezentari`), nu doar prin apel intern. RAR test = endpoint real.
### 5.2 Cele 4 faze (separabile pe sesiuni)
```
SESIUNE A (Opus/Fable) SESIUNE B (lead + agent team Sonnet)
┌─────────────────────┐ ┌──────────────────────────────────────────────────┐
│ FAZA 1: PLAN │ PRD │ FAZA 2: EXECUTE FAZA 3: VERIFY FAZA 4: CLOSE │
│ citeste ROADMAP+cod │ aprobat │ TeamCreate + subagent context /code-review │
│ scrie PRD (stories │ ───────▶ │ workeri Sonnet curat: pytest + writeback dash │
│ atomice + teste) │ (in PRD) │ TDD per story E2E RAR test propune commit │
│ plan-reviews gstack │ │ lead bifeaza PRD raport in PRD │
│ ▼ POARTA UMANA │ │ ▼ POARTA UMANA │
│ aprobare PRD │ │ confirmare commit│
└─────────────────────┘ └──────────────────────────────────────────────────┘
```
PLAN poate rula singur intr-o sesiune (scump, model puternic) si se opreste la poarta de aprobare.
EXECUTE → VERIFY → CLOSE reiau intr-o sesiune noua din PRD-ul aprobat. Pot fi si inlantuite in
aceeasi sesiune daca vrei — starea din PRD le face reluabile oricum.
### 5.3 PRD per livrabila
- **1 PRD per livrabila** din dashboard: `docs/prd/prd-X.Y-<slug>.md` (skill `/prd`).
- Prima linie dupa titlu: `**Stare**: draft` (vezi §5.7 pentru tranzitii).
- Contine obligatoriu: obiectiv, **Non-Goals** (anti scope-creep), stories atomice (§5.4),
riscuri, intrebari deschise (rezolvate cu utilizatorul ÎNAINTE de executie), graful de valuri.
- PRD-ul **nu repeta** strategia/contractul — le linkeaza (`docs/api-rar-contract.md`, acest ROADMAP).
- **Review-uri de plan** (aplicate IN PRD inainte de cod): `/plan-ceo-review` (valoare/scope) +
`/plan-eng-review` (fezabilitate/teste) — obligatorii; `/plan-design-review` — doar daca atinge UI.
### 5.4 Story atomic (template)
```markdown
### US-003: <titlu scurt>
**Ca** <rol> **vreau** <capabilitate> **pentru ca** <motiv>.
- **Depinde de**: US-001
- **Fisiere**: `app/<modul>.py`, `app/web/templates/<x>.html` (~N fisiere)
- **Test intai (RED)**: `tests/test_<x>.py``test_<caz_1>`, `test_<caz_2>`
- **Acceptance criteria**:
- [ ] <criteriu testabil 1>
- [ ] <criteriu testabil 2>
- **Verificare E2E**: <browser HTMX / POST /v1/prezentari pe RAR test>
```
Testul de atomicitate: (a) poate un Sonnet sa-l termine intr-o singura sesiune, cu teste, fara sa
intrebe nimic? daca nu → sparge-l. (b) lasa sistemul **functional** daca e ultimul story? (c) `Fisiere`
+ `Depinde de` complete (decid ce se paralelizeaza). (d) backend + UI pentru acelasi comportament = **2 stories**.
### 5.5 Executie — agent team (lead orchestreaza, NU scrie cod)
- `TeamCreate` creeaza echipa + lista de task-uri partajata; `Agent` cu `team_name` + `name` +
`model: sonnet` spawneaza **teammates adresabili**. Lead-ul ii coordoneaza prin `SendMessage`
(clarificari/re-directionare la cald, fara re-spawn) si `TaskUpdate` (atribuire/inchidere task).
- **Valuri (waves):** lead-ul grupeaza stories pe graful de dependente. Val 1 = stories fara
`Depinde de` si fara fisiere comune → teammates paraleli. Val 2 = deblocate de Val 1. Etc.
- **Reguli hard:** max 2-3 teammates simultan (server dev + SQLite partajate); **fisiere comune = nu
paralel** (sau `isolation: worktree` + merge de catre lead); teammates **nu** comit, nu scriu in
PRD/ROADMAP, nu pornesc/opresc servere, nu rezolva ambiguitati singuri (escaladeaza la lead).
- **Raport teammate** (prin `SendMessage`): test RED citat → implementare → test GREEN citat →
fisiere atinse → abateri; apoi `TaskUpdate``completed`.
- Dupa fiecare val: lead-ul ruleaza regresia (`python3 -m pytest -q`) si bifeaza stories in PRD.
- Livrabile mici pot rula **fara TeamCreate** (un singur worker sau lead direct) — dar PRD-ul,
verificarea in context curat si writeback-ul raman obligatorii.
### 5.6 VERIFY (subagent cu context curat)
Lead-ul spawneaza un subagent dedicat care primeste DOAR PRD-ul + aceste instructiuni, NU transcriptul:
> Esti verificator independent pentru livrabila {X.Y} (PRD: `docs/prd/prd-{X.Y}-<slug>.md`).
> Citeste PRD-ul; NU porni de la premisa ca implementarea e corecta.
> 1. Suita: `python3 -m pytest -q` — verde (citeaza output-ul).
> 2. Criteriile de acceptare ale fiecarui story din PRD.
> 3. E2E pe canalul atins: UI web → `./start.sh test both --send`, browser pe `http://localhost:8000/`
> (Playwright MCP sau `/browse`), fluxul din PRD; canal API → `POST /v1/prezentari` pe RAR test.
> 4. **Regresia de aur:** fluxul existent nu are voie sa se strice — `POST /v1/prezentari` (sau
> import → commit) → worker → `FINALIZATA` la RAR test, vizibil in dashboard (`./start.sh test finalizate`).
> 5. Raport PASS/FAIL per criteriu cu dovezi. FAIL-urile NU le repari (`/qa-only`, nu `/qa`) — le documentezi.
Lead-ul scrie raportul in PRD ca `## Raport VERIFY`. Toate PASS → CLOSE. Exista FAIL → inapoi la
EXECUTE (stories de fix), apoi VERIFY din nou cu subagent NOU.
### 5.7 Bootstrap sesiune (detectie faza din starea PRD)
Starea persista in PRD (prima linie dupa titlu), actualizata de lead la fiecare tranzitie:
`**Stare**: draft → aprobat → in-executie → verify-pass → inchis`. Asta face procesul reluabil
din orice sesiune noua — starea e in fisiere, nu in conversatie.
| Stare gasita | Faza de pornire |
|---|---|
| nu exista `docs/prd/prd-{X.Y}-*.md` | PLAN |
| PRD `**Stare**: draft` | PLAN (reia stories/review-uri) |
| PRD `**Stare**: aprobat` / `in-executie`, stories nebifate | EXECUTE |
| toate stories bifate, fara `## Raport VERIFY` cu PASS | VERIFY |
| `## Raport VERIFY` = PASS | CLOSE |
| PRD `**Stare**: inchis` | livrabila gata — alege urmatoarea din dashboard |
La bootstrap: daca utilizatorul a numit `{X.Y}`, aceea e; altfel prima `WIP` din dashboard, apoi
prima `TODO` in ordinea etapelor. **Confirma alegerea cu utilizatorul** — singura intrebare permisa la start.
### 5.8 CLOSE + porti umane
1. `/code-review` pe diff-ul livrabilei. Probleme → fix acum (worker) sau story nou (inapoi in PRD).
2. **Writeback:** in §3 dashboard — status `DONE` + data + link PRD; actualizeaza "Ultima actualizare".
PRD: `**Stare**: inchis`.
3. **POARTA UMANA:** propune commit-ul (mesaj conventional commits, fara emoji; vezi git rules) si
ASTEAPTA confirmarea explicita — niciodata commit automat.
### 5.9 Anti-patterns (opreste-te daca observi)
| Anti-pattern | Corectia |
|---|---|
| Teammate "termina" fara output de test citat | Raportul e invalid — cere dovezi prin `SendMessage` |
| Test scris DUPA implementare ca formalitate | Nu e TDD — testul e contractul; refa bucla |
| Lead-ul scrie cod "ca e mai rapid" | Pierde orchestrarea; spawn teammate chiar si pt un fix mic |
| Stories paralele care ating acelasi fisier | Re-planifica valurile sau worktree + merge de catre lead |
| PRD modificat in executie fara re-review | Schimbare de scope → inapoi la PLAN |
| Lead verifica singur, fara subagent VERIFY | Partinire de confirmare — VERIFY cere context proaspat |
| Continua peste poarta umana | Aprobarea PRD si confirmarea commit sunt ale utilizatorului — opreste-te |
---
## 6. Skill-uri in proces
| Faza | Skill | Rol |
|------|-------|-----|
| PLAN | `/prd` | genereaza PRD-ul (`docs/prd/prd-X.Y-<slug>.md`) |
| PLAN | `/plan-ceo-review`, `/plan-eng-review`, `/plan-design-review` | review de plan (primele 2 obligatorii; design doar UI) |
| EXECUTE | `/investigate` | bug neinteles raportat de worker — root cause, nu patch orb |
| VERIFY | `/browse`, `/qa-only` | browser headless / QA doar-raport (nu repara — pastreaza independenta) |
| CLOSE | `/code-review` | review pe diff-ul livrabilei |
| oricand | `/learn` | salveaza gotcha-uri in `.claude/rules/` (nu in acest doc) |
---
## 7. Intretinere
Acest document se actualizeaza la **schimbari de proces** (nu per livrabila) si la **dashboard**
(la fiecare livrabila terminata — §3). Lectiile operationale (gotchas, pattern-uri descoperite in
executie) merg in `.claude/rules/` via `/learn`, nu aici.