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>
300 lines
89 KiB
Markdown
300 lines
89 KiB
Markdown
# 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 768–1024). 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.
|