- docs/prd/prd-5.9-ux-corectie-modal-mobil.md: PRD aprobat (8 stories, raport AUTOPLAN) - scripts/ralph/: ralph.sh + prompt.md (smart-gates) + progress.txt - scripts/ralph/prd.json: 8 user stories cu reviziile obligatorii R1-R12 incorporate in acceptance criteria; priority encodeaza valurile de dependente - .gitignore: runtime Ralph (logs/screenshots/archive/.last-branch/usage.jsonl) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
38 KiB
PRD 5.9 — Corectie inline in modal + consolidare actiuni + design mobil
Stare: draft
Proces:
docs/ROADMAP.md§5. Contract RAR (sursa de adevar):docs/api-rar-contract.md. Starea trece:draft → aprobat → in-executie → verify-pass → inchis.
1. Obiectiv
Curatenie UX pe ecranul de Trimiteri, fara nicio schimbare a fluxului de trimitere catre RAR. Raportat de utilizator dupa 5.8: containerul de detaliu s-a aglomerat si nu mai e clar la ce sa te uiti. Sase corectii, toate UI/prezentare:
- Detaliul + corectia trec intr-un formular MODAL (overlay centrat, in afara zonei
#submissions-wrapreincarcata la 15s). Rezolva direct bug-ul „formularul se inchide singur dupa cateva secunde / se sterg bifele" (azi randul-sibling de detaliu traieste IN regiunea de poll, iar bifele de bulk se pierd la fiecare refresh) si „nu se distinge marginea containerului de restul tabelului" (overlay clar delimitat). Inlocuieste abordarea inline-row din 5.8 US-008. - Editare in-place fara dublarea valorilor: azi fiecare camp apare de DOUA ori in detaliu — o
data read-only (
_trimitere_detaliu.html:19-32) si inca o data ca input in „Corecteaza si re-trimite" (:130-156). Modalul afiseaza fiecare camp O SINGURA DATA, direct editabil. - Consolidarea butoanelor: azi „Re-pune in coada", „Sterge" si „Salveaza si re-pune in coada"
sunt imprastiate in 2 locuri cu culori similare (
:53-69+:153-155), plus „Sterge selectate" bulk pe tabel. Ramane un singur buton principal „Salveaza si retrimite" (salvarea repune mereu in coada; retry pur = salvezi fara modificari) + un „Sterge" rosu, vizibil distantat. Bulk „Sterge selectate" ramane DOAR pe tabel. - Fara chevron pe randuri (
_submissions.html:53) — inutil odata ce detaliul e modal. - Codul de eroare in tabel, sub eticheta de stare (ex.
RAR_EROARE_SERVER,COD_NEMAPAT), doar pe randurile cu problema — fara coloana noua (prietenos mobil). - Cod RAR simplu in tabel (fara prefixul „cod RAR:",
_submissions.html:66) si in modal (fara campul etichetat „Cod RAR" separat — codul apare langa operatie).
Plus, transversal: design responsive/mobil pentru TOATE paginile dashboard (azi exista carduri doar pe tabelul de trimiteri sub 768px, din 5.8; restul paginilor — Mapari, Cont, Nomenclator, Integrare, Jurnal, Admin, login/signup — si modalul nou nu au tratament mobil).
2. Non-Goals (anti scope-creep)
- Fara modificari la worker, masina de stari, contractul RAR, idempotenta sau logica de mapare.
Rutele backend (
/corecteaza,/repune,/sterge,/mapeaza,/sterge-bulk) raman ca semnatura si comportament — se schimba DOARhx-target-ul (modalul) si prezentarea. - Fara redesign vizual al continutului paginilor (culori, tipografie, structura de informatie) — doar adaptare responsive (stivuire, latimi, tinte touch) pe layout-ul existent.
- Fara animatii elaborate de deschidere modal — un fade/scale simplu e destul (APP UI).
- Nu schimbam ce campuri sunt editabile (raman
nr_inmatriculare,vin,data_prestatie,odometru_final,odometru_initial) si nici validarea lor (corecteazaneatins logic). - Fara stergerea sectiunii de mapare inline (5.7) — se muta ca atare in modal.
- Fara framework CSS nou (Bootstrap/Tailwind) — extindem variabilele si
base.htmlexistente.
3. Stories atomice
Backend/date + UI pentru acelasi comportament = stories separate.
Fisiere+Depinde decomplete decid paralelizarea.
US-001: cod_eroare scurt disponibil pe randul de afisare
Ca dezvoltator vreau codul de eroare (cheia din catalog) expus pe randul tabelului
pentru ca sa-l pot afisa sub eticheta de stare fara sa re-parsez rar_error in template.
- Depinde de: —
- Fisiere:
app/web/routes.py(_submission_row_view),app/web/labels.py(helper extragere cod),tests/test_web_submissions.py - Test intai (RED):
tests/test_web_submissions.py—test_cod_eroare_prezent_pe_rand_error,test_cod_eroare_prezent_pe_needs_mapping,test_cod_eroare_gol_pe_rand_ok - Acceptance criteria:
_submission_row_viewintoarce in pluscod_eroare: str= codul scurt din catalog (app/errors.pycod, ex.RAR_EROARE_SERVER,COD_NEMAPAT) extras dinrar_error(superset 5.4) sau derivat dinstatuscand nu existarar_error(ex.needs_mapping → COD_NEMAPAT). Sir gol pe stari fara problema (queued/sending/sent).- Extragerea e un helper pur in
labels.py(ex.cod_eroare_din(status, rar_error) -> str), defensiv larar_errorlipsa/JSON invalid (intoarce"", nu ridica). prez,motiv,stare_*raman neschimbate (aditiv).python3 -m pytest tests/test_web_submissions.py -qtrece.
- Verificare E2E: —
US-002: Tabel trimiteri — cod eroare sub stare, fara chevron, cod RAR simplu
Ca operator vreau sa vad codul problemei direct in tabel si un rand mai curat pentru ca sa stiu dintr-o privire ce rand are nevoie de mine.
- Depinde de: US-001, US-003 (randul declanseaza modalul)
- Fisiere:
app/web/templates/_submissions.html,app/web/templates/base.html(CSS),tests/test_web_submissions.py - Test intai (RED):
tests/test_web_submissions.py—test_cod_eroare_apare_sub_pill,test_fara_chevron_in_rand,test_cod_rar_fara_prefix_text,test_rand_deschide_modal - Acceptance criteria:
- Sub pill-ul de Stare apare
r.cod_eroare(text mic, muted,s-errorpeerror/needs_*), DOAR cand e ne-gol. Nu se transmite stare doar prin culoare (codul e text). - Chevron eliminat din coloana
#(_submissions.html:52-53) si din CSS/JS asociat. - Coloana Operatie linia 2: doar codul (ex.
OE-2), fara prefixul „cod RAR:" — un<span>muted/pill; cand nemapat afiseaza „nemapat" muted (comportament 5.8 pastrat). - Randul (
tr.trimitere-row) declanseaza deschiderea modalului (US-003):hx-get /_fragments/trimitere/{id}cuhx-targetpe corpul modalului, NU pe un rand-sibling. Randul-sibling<tr class="detaliu-rand">din 5.8 este eliminat. - Pe touch tinta randului ramane >=44px; randul ramane
role="button",tabindex="0", focusabil; Enter/Space deschid modalul. python3 -m pytest tests/test_web_submissions.py -qtrece.
- Sub pill-ul de Stare apare
- Verificare E2E: gstack browser pe
/— un randerrorarata codul sub pill; nu exista chevron; codul RAR apare fara „cod RAR:"; click pe rand deschide modalul (nu rand-sibling).
US-003: Component modal reutilizabil (overlay, focus-trap, a11y)
Ca operator vreau ca detaliul sa apara intr-o fereastra modala clar delimitata pentru ca sa nu mai confund marginea cu tabelul si sa nu mi se mai inchida formularul la refresh.
- Depinde de: —
- Fisiere:
app/web/templates/base.html(markup#modal-detaliu+ CSS + JS),app/web/templates/_coada.html(ancora globala in afara#submissions-wrap),tests/test_web_modal.py - Test intai (RED):
tests/test_web_modal.py—test_modal_container_in_afara_submissions_wrap,test_fragment_detaliu_tinteste_modalul - Acceptance criteria:
- Container modal global
<div id="modal-detaliu" role="dialog" aria-modal="true" hidden>cu backdrop, plasat in afara#submissions-wrap(deci poll-ul de 15s nu-l atinge). Corpul modalului (#detaliu-modal-body) e tinta de swap pentru fragmentul de detaliu si pentru rutele de corectie/mapare/lifecycle. - Deschidere: la
htmx:beforeRequestde pe untr.trimitere-row, se arata backdrop+dialog (placeholder „Se incarca…" prinhx-indicatorpana raspunde HTMX) si se muta focusul in modal. Un singur modal o data. - Inchidere prin: buton
x, tastaEsc, click pe backdrop. La inchidere:hidden, corpul golit, focus readus pe randul declansator. - Focus-trap: Tab/Shift+Tab cicleaza in interiorul modalului cat e deschis; restul paginii
primeste
aria-hidden/inert(sau echivalent). Scroll-ul body blocat cat modalul e deschis. - Tot codul inline-expand din 5.8 (chevron,
tr.detaliu-rand,marcheazaDetaliuDeschis,inchideDetaliupe rand, toggle single-open pe rand) este inlocuit de logica modalului;window.inchideDetaliu(id)ramane expus (apelat de butonul „Inchide") dar inchide modalul. #trimitere-detaliuglobal inert din_coada.htmleste eliminat (rolul lui e preluat de#modal-detaliu).python3 -m pytest tests/test_web_modal.py -qtrece.
- Container modal global
- Verificare E2E: gstack browser pe
/— click pe rand deschide modal centrat cu fundal estompat; Esc / click-afara / x inchid si readuc focusul; Tab nu paraseste modalul.
US-004: Detaliu editabil in-place + butoane consolidate (in modal)
Ca operator vreau sa corectez datele direct, o singura aparitie per camp, cu un buton clar pentru ca sa nu mai vad valorile de doua ori si sa nu mai ezit intre butoane.
- Depinde de: US-003
- Fisiere:
app/web/templates/_trimitere_detaliu.html,app/web/routes.py(_detaliu_ctx— doar context de prezentare, fara logica noua),tests/test_web_corectie.py - Test intai (RED):
tests/test_web_corectie.py—test_camp_apare_o_singura_data,test_nr_si_vin_pe_randuri_separate,test_un_singur_buton_salveaza,test_fara_buton_repune_separat,test_sterge_prezent_si_distinct,test_corectie_pastreaza_comportament(regresie pe ruta) - Acceptance criteria:
- Zero dublare: blocul read-only de grila (
_trimitere_detaliu.html:19-32) si formularul separat de corectie se contopesc intr-un singur formular cu campuri editabile pre-completate. Campurile editabile (nr_inmatriculare,vin,data_prestatie,odometru_final,odometru_initial) apar O SINGURA DATA. - Layout cerut:
Numar inmatricularepe propriul rand (latime plina),VIN (serie sasiu)pe randul de DEDESUBT (latime plina). Restul campurilor pot ramane in grila. - Cod RAR simplu: nu mai exista campul etichetat „Cod RAR" separat (
:23); operatia + codul RAR rezolvat apar impreuna, ca context read-only (ex. „Operatie: Revizie · OE-2"), fara eticheta „Cod RAR". Campurile pur contextuale (Nr. prezentare RAR, Cod HTTP, Reincercari, timestampuri) raman read-only. - Un singur buton principal
Salveaza si retrimite(clasa primara) — posteaza pe/trimitere/{id}/corecteaza(neschimbat); salvarea repune mereu in coada (retry pur = salvezi fara a schimba nimic). Butonul „Re-pune in coada" gol (:55-59) este eliminat. - Un singur
Sterge(clasa distructiva, rosu,var(--err)), plasat vizibil distantat de butonul principal (ex.margin-left:auto/ rand separat), cuhx-confirm. Posteaza pe/trimitere/{id}/sterge(neschimbat). - Sectiunea de mapare inline (5.7,
:71-116) ramane functional identica, mutata in modal, tintind corpul modalului. - Erorile de camp (
err_map,aria-invalid, mesaj inline) si flash-ul de corectie raman. - Comportamentul rutei
/corecteaza(validare, idempotency, re-rezolvare) e neschimbat — testul de regresie confirma acelasi rezultat ca azi. python3 -m pytest tests/test_web_corectie.py -qtrece.
- Zero dublare: blocul read-only de grila (
- Verificare E2E: gstack browser — deschid un rand
needs_data, vad fiecare camp o singura data (nr. pe un rand, VIN dedesubt), corectez data,Salveaza si retrimite→ randqueued;Stergee clar separat si rosu.
US-005: Poll-ul nu mai inchide modalul si nu mai sterge bifele
Ca operator vreau ca selectia si modalul sa supravietuiasca refresh-ului de 15s pentru ca azi formularul se inchide singur si bifele se sterg dupa cateva secunde.
- Depinde de: US-002, US-003
- Fisiere:
app/web/templates/base.html(JS poll-guard),app/web/templates/_coada.html,tests/test_web_modal.py - Test intai (RED):
tests/test_web_modal.py—test_poll_pauzat_cat_modal_deschis,test_poll_pauzat_cat_exista_bifa - Acceptance criteria:
- Modalul traieste in afara
#submissions-wrap→ un swap de poll NU il mai atinge (rezolvat structural de US-003). Test: cu modalul deschis, un refresh al listei nu-l inchide. - Poll-ul de 15s (
#submissions-wrap,_coada.html:62-65) se pune pe pauza lahtmx:beforeRequestcat timp: (a) modalul e deschis SAU (b) exista cel putin un checkbox de bulk bifat. Se reia automat cand ambele conditii dispar. - La pauza nu se pierde nici scroll, nici focus, nici selectia de checkbox-uri.
- Logica veche de pauza pe „rand expandat" (5.8,
base.html:478-483) este inlocuita de aceasta. python3 -m pytest tests/test_web_modal.py -qtrece.
- Modalul traieste in afara
- Verificare E2E: gstack browser — bifez 2 trimiteri, astept >15s: bifele raman; deschid modalul, astept >15s: modalul ramane deschis cu datele intacte.
US-006: Fundatie responsive — header, nav, modal, breakpoint-uri
Ca utilizator pe telefon vreau ca shell-ul aplicatiei sa fie utilizabil pentru ca azi header-ul, tab-bar-ul si modalul nou nu au tratament sub 768px.
- Depinde de: US-003 (modalul exista)
- Fisiere:
app/web/templates/base.html(CSS responsive +<meta viewport>verificat),tests/test_web_responsive.py - Test intai (RED):
tests/test_web_responsive.py—test_viewport_meta_prezent,test_modal_fullscreen_clasa_mobil,test_nav_colapsabil_sub_breakpoint - Acceptance criteria:
<meta name="viewport" content="width=device-width, initial-scale=1">prezent (confirmat/adaugat).- Modal full-screen pe mobil: sub 768px modalul ocupa tot ecranul (fara backdrop lateral),
cu buton
xmare (>=44px) si scroll intern; pe desktop ramane centrat cu latime marginita. - Header + nav: meniul de cont (☰) si tab-bar-ul nu depasesc latimea pe 375px; tintele touch >=44px; fara scroll orizontal pe pagina.
- Breakpoint-uri consistente definite o data (ex.
--bp-mobil: 768px) si reutilizate; fara regresie pe desktop (>=1024px arata identic). python3 -m pytest tests/test_web_responsive.py -qtrece.
- Verificare E2E: gstack browser la 375px pe
/— fara scroll orizontal; ☰ deschide meniul; modalul deschis ocupa tot ecranul si se inchide dinx.
US-007: Responsive — paginile de continut (Mapari, Cont, Nomenclator, Integrare, Jurnal, Admin)
Ca operator pe telefon vreau ca paginile de lucru sa fie lizibile pentru ca tabelele si formularele lor ies azi din ecran sub 768px.
- Depinde de: US-006
- Fisiere:
app/web/templates/_mapari.html,_cont.html,_nomenclator.html,_integrare.html,_jurnal.html,admin.html,base.html(utilitar.tablewrap/card),tests/test_web_responsive.py - Test intai (RED):
tests/test_web_responsive.py—test_tabele_continut_au_clasa_responsive,test_formulare_full_width_mobil - Acceptance criteria:
- Fiecare tabel din paginile listate fie devine card per rand sub 768px (model 5.8
.tabel-trimiteri), fie e incadrat intr-un.tablewrapcu scroll orizontal contained (nu deborda pagina) — alegere per tabel, documentata in §7. - Formularele (Cont, Mapari add-row, filtre, Integrare) stiveaza campurile pe o coloana sub 768px, inputuri full-width, butoane >=44px.
- La 375px niciuna din pagini nu produce scroll orizontal de pagina (
scrollWidth <= clientWidthpebody). - Fara regresie la >=1024px (layout actual pastrat).
python3 -m pytest tests/test_web_responsive.py -qtrece.
- Fiecare tabel din paginile listate fie devine card per rand sub 768px (model 5.8
- Verificare E2E: gstack browser la 375px pe
/?tab=mapari,?tab=jurnal, meniul Cont/Nomenclator/ Integrare si/admin— fiecare fara scroll orizontal, tabele lizibile, formulare pe o coloana.
US-008: Responsive — Acasa (upload, status, filtre) + login/signup
Ca utilizator pe telefon vreau ca prima pagina si autentificarea sa fie utilizabile pentru ca sunt punctele de intrare si azi nu au tratament mobil complet.
- Depinde de: US-006
- Fisiere:
app/web/templates/_acasa.html,_upload.html,_status.html,_coada.html(filtre),login.html,signup.html,tests/test_web_responsive.py - Test intai (RED):
tests/test_web_responsive.py—test_acasa_fara_scroll_orizontal_mobil,test_login_signup_full_width_mobil - Acceptance criteria:
- Zona de upload, bara de status (US-002 5.x) si bara de filtre (
_coada.html:25-59) stiveaza pe o coloana sub 768px; inputuri/butoane full-width >=44px. - Tabelul de trimiteri pastreaza cardurile din 5.8 (verificat, nereparat daca deja ok).
login.htmlsisignup.html: card centrat care nu depaseste latimea pe 375px, inputuri full-width, fara scroll orizontal.- Fara regresie la >=1024px.
python3 -m pytest tests/test_web_responsive.py -qtrece.
- Zona de upload, bara de status (US-002 5.x) si bara de filtre (
- Verificare E2E: gstack browser la 375px pe
/,/login,/signup— fara scroll orizontal; upload + filtre pe o coloana; carduri de trimiteri intacte.
4. Riscuri
- Inlocuirea inline-expand (5.8 US-008) cu modal atinge JS partajat din
base.html(toggle, poll, focus). Risc de regresie pe a11y/keyboard. Mitigare: testele US-003/US-005 + E2E pe tastatura; pastramwindow.inchideDetaliuca punct de inchidere stabil. - Focus-trap +
inert/aria-hiddenpe restul paginii: implementat gresit, poate „inchide" tastatura sau lasa scroll body. Mitigare: pattern dialog standard, test de ciclare Tab. - Poll-pauza pe „exista bifa" (US-005): daca verificarea citeste DOM la fiecare
beforeRequest, costul e neglijabil, dar trebuie sa prinda si bifele adaugate dupa randare (delegare pe body). - Carduri vs scroll contained (US-007): tabelele de continut sunt eterogene (Jurnal e lung,
Nomenclator e dens). Alegerea per tabel trebuie sa nu rupa
.tablewrappartajat — scopare prin clasa, ca in 5.8. - Reversibilitate: 5.8 a livrat inline-row recent; 5.9 il scoate. De confirmat ca nicio alta
pagina nu mai depinde de
tr.detaliu-rand/#trimitere-detaliuinainte de stergere.
5. Intrebari deschise
Rezolvate cu utilizatorul INAINTE de executie (poarta de aprobare PRD).
Inline reproiectat vs modal vs drawer pentru detaliu?REZOLVAT (sesiune 2026-06-24): modal.Editare: in-place vs citire+toggle Editeaza?REZOLVAT: editare in-place (campuri o singura data).Pastram un buton separat „Re-pune fara modificari" pentru randuri error?REZOLVAT: NU — un singur „Salveaza si retrimite" (retry pur = salvezi fara modificari).Codul de eroare in tabel: coloana noua sau sub stare?REZOLVAT: sub eticheta de stare.- Tabele de continut (US-007): care devin carduri si care raman scroll-contained? — de decis per tabel la executie (default: tabele scurte/actionabile = carduri; Jurnal/Nomenclator = scroll contained). Neblocant.
6. Valuri de executie (graful de dependente)
Val 1: [US-001] [US-003] [US-006] ← fara dependente intre ele (US-006 dep US-003 pt modal mobil
dar poate incepe pe shell); fisiere majoritar disjuncte
Val 2: [US-002] [US-004] [US-007] [US-008]
US-002 dep US-001+US-003 · US-004 dep US-003 · US-007/US-008 dep US-006
Val 3: [US-005] ← dep US-002+US-003 (selectie + modal)
7. Decizii de design (din sesiunea de clarificare, 2026-06-24)
Container detaliu = MODAL
Overlay centrat, fundal estompat, in afara zonei de poll. Rezolva simultan trei reclamatii:
(a) „marginea nu se distinge de tabel" (overlay delimitat clar), (b) „formularul se inchide singur /
se sterg bifele" (modal in afara #submissions-wrap + pauza poll), (c) aglomerarea (un singur set de
campuri editabile). Pe mobil = full-screen.
Editare in-place (campuri o singura data)
Campurile editabile SUNT formularul, pre-completate. Nr. inmatriculare pe propriul rand, VIN dedesubt. Contextul pur read-only (Nr. prezentare RAR, Cod HTTP, reincercari, timestampuri) ramane, dar operatie+cod RAR se afiseaza impreuna, fara eticheta „Cod RAR".
Actiuni consolidate
Un primar Salveaza si retrimite (albastru) + un Sterge distructiv (rosu) clar distantat. „Re-pune
in coada" gol eliminat (salvarea repune). Bulk „Sterge selectate" ramane DOAR pe tabel. Culori clar
diferentiate primar vs distructiv (azi ambele aproape de --card/outline).
Tabel: cod eroare sub stare, fara chevron, cod RAR simplu
Sub pill apare codul scurt (cod_eroare) doar pe randuri cu problema. Chevron scos. Codul RAR in
coloana Operatie fara prefixul „cod RAR:".
Responsive (transversal)
>=1024px: layout actual neschimbat (fara regresie).<768px: tabelul de trimiteri = carduri (5.8, pastrat); modal = full-screen; nav/header colapsate; formulare pe o coloana, inputuri/butoane full-width, tinte touch >=44px; alte tabele = carduri sau scroll contained (per tabel). Fara scroll orizontal de pagina pe niciuna din pagini.
Tabel stari interactiune
FEATURE | LOADING | EMPTY | ERROR | SUCCESS
---------------------|------------------------|------------------|------------------------|------------------
Rand -> Modal | placeholder „Se incarca| n/a | fragment eroare HTMX | detaliu in modal
| …" (hx-indicator) | | in corpul modalului | centrat/full-screen
Cod eroare sub pill | — | (ascuns pe rand | cod scurt (s-error) | (ascuns pe rand OK)
| | OK) | |
Corectie in modal | buton disabled la post | — | mesaj flash + campuri | rand -> queued, modal
| | | invalide marcate | se inchide / reincarca
8. NU in scope (design — deferat explicit)
- Redesign de continut/IA al paginilor (doar adaptare responsive).
- Drawer lateral ca alternativa la modal (respins in favoarea modalului).
- Buton „Re-pune fara modificari" separat (respins — un singur flux de salvare).
- Coloana dedicata „Problema" in tabel (respins — cod sub pill).
- Animatii de expand/collapse / tranzitii elaborate de modal.
9. Ce exista deja (de reutilizat, nu reinventat)
- Fragment detaliu
GET /_fragments/trimitere/{id}+_detaliu_ctx(routes.py:819,:880) — corpul ramane, se schimba doar containerul-tinta (modal). - Rute lifecycle/corectie/mapare:
/trimitere/{id}/corecteaza|sterge|mapeaza+ bulk/trimiteri/sterge-bulk— neatinse logic, doarhx-target. eticheta_stare/eticheta_scurta/motiv_uman(labels.py) + catalogapp/errors.py(cod scurt).- Carduri responsive
.tabel-trimiteri(<768px) din 5.8 — model reutilizat pentru celelalte tabele. - Macro
auto_sendtoggle + select nomenclator +csrf_token— sectiunea mapare inline le pastreaza. - Variabile CSS / teme dark-light (
base.html), clase pills-*, clasa.flash.
Raport VERIFY
Completat de subagentul verificator (context curat) in faza VERIFY — vezi ROADMAP §5.6. PASS/FAIL per criteriu, cu dovezi (output pytest citat, E2E pe RAR test). Lipseste pana la VERIFY.
AUTOPLAN REVIEW REPORT
Branch: main · Commit: 32408ed · Generat: 2026-06-24 · Voci: Claude subagent (Codex indisponibil — limita de utilizare)
Faza 1 — CEO (Strategie & Scope) [subagent-only]
CEO DUAL VOICES — CONSENSUS TABLE
Dimensiune Claude Codex Consensus
───────────────────────────────────────────────────────────────────
1. Premise valide? PARTIAL N/A PARTIAL (vezi F3,F8)
2. Problema corecta de rezolvat? DA* N/A DA cu rezerve (F1)
3. Calibrare scope corecta? NU N/A NU (F5/F6 responsive mis-bundled)
4. Alternative explorate suficient? NU N/A NU (F4 rezolvat prin fiat)
5. Riscuri competitive/piata acoperite? PARTIAL N/A PARTIAL (F6 mobil nevalidat)
6. Traiectorie 6 luni sanatoasa? PARTIAL N/A PARTIAL (F2 churn 5.8->5.9)
Codex N/A (limita de utilizare). Constatari critice de la subagent flagate oricum.
Constatari CEO (subagent independent)
- F1 (critical, strategic): produs cu zero utilizatori reali; a 9-a slefuire UX interna fara semnal de cerere. Recomanda validare cu un operator real inainte de redesign. → context la poarta, nu blocant (userul a ales /autoplan pe acest PRD).
- F2 (high): scoaterea UI-ului inline-row din 5.8 o singura iteratie mai tarziu = churn vizibil; bug-ul real e ca plan-review-ul a lasat 5.8 sa livreze un UI care se auto-distruge sub poll-ul existent. → retro, nu blocant.
- F3 (high): premisa-titlu (modalul rezolva „formularul se inchide singur") e partial gresita — un poll-pause + scoaterea selectiei din
#submissions-wraprezolva bug-ul fara modal. Modalul e preferinta de design, nu cerinta de bug. → POARTA premise. - F4 (medium): alternativele (inline reproiectat, drawer) respinse fara rationament inregistrat. → auto: pastram modalul (decizie utilizator 2026-06-24), dar notam ca preferinta de produs.
- F5 (high, scope): responsive-pentru-toate-paginile (US-006/007/008) mis-bundled cu cleanup-ul modal; e jumatatea mai mare si mai riscanta, aproape disjuncta in graful de dependente. → POARTA scope (split vs bundle).
- F6 (high, piata): mobil sub 768px probabil rezolva o non-problema — operatorii service-auto declara de la birou pe PC (inlocuiesc o app VFP desktop). → POARTA (legat de F5).
- F7 (medium): consolidarea butoanelor ruteaza retry pur prin
/corecteazain loc de/repune— schimbare de comportament ascunsa intr-un PRD „doar prezentare". → auto (Eng): test de regresie explicit pe retry-fara-editare + idempotenta. - F8 (medium): codul brut de catalog (
RAR_EROARE_SERVER,COD_NEMAPAT) sub pill contrazice investitia 5.4 in erori umane (problema/cauza/fix). → POARTA premise (cod brut vs eticheta umana).
POARTA PREMISE (decizii utilizator, 2026-06-24)
- D1 = Keep all 8 bundled: responsive (US-006/007/008) RAMANE in 5.9. Risc F5/F6 acceptat constient.
- D2 = Eticheta umana pe rand: US-001/US-002 REVIZUITE — sub pill apare o eticheta umana scurta (nu codul brut
RAR_EROARE_SERVER); codul brut de catalog ramane in modal pentru suport. (Schimbare fata de PRD original.) - D3 = Modal (confirmat): se construieste modalul (US-003) + poll-pause (US-005). Decizia 2026-06-24 sustinuta.
Faza 2 — Design (UI/UX) [subagent-only] · Completitudine: 6.5/10
Design litmus (consensus, Codex N/A)
Hierarchy: ISSUE ordinea verticala a modalului nedefinita -> reproduce „zidul" de campuri (F1)
States: ISSUE load-error poate ramane blocat; succes corectie „inchide/reincarca" contradictoriu; mapare/sent absente (F2)
Consolidation: ISSUE margin-left:auto gresit (se prabuseste pe mobil); primar --accent + disable-on-submit neimpuse (F4)
A11y: ISSUE focus dupa swap, inert+aria-hidden ambele, aria-labelledby lipsa (F5)
Responsive: ISSUE card-vs-scroll punt ascunde cost 5x (data-eticheta) + poate ascunde controale (F6)
Specificity: ISSUE contradictie D2 vs US-001/002 (F3)
Constatari: F1(critical) ordine modal; F2(high) stari modal; F3(high) D2 vs US-001/002; F4(high) separare buton distructiv; F5(med/high) a11y post-swap; F6(med) card-vs-scroll + data-eticheta; F7(med) operatie+cod nemapat; F8(low) afordanta rand fara chevron.
Faza 3 — Eng (Arhitectura & Test) [subagent-only]
ENG DUAL VOICES — CONSENSUS TABLE
Dimensiune Claude Codex Consensus
───────────────────────────────────────────────────────
1. Arhitectura solida? ISSUE N/A ISSUE (F1,F2 stale tests + script fragment)
2. Acoperire test suf.? ISSUE N/A ISSUE (teste stale nelistate + lipsa focus/poll/keyboard)
3. Riscuri perf? OK N/A OK (poll-pause cost neglijabil)
4. Securitate? OK N/A OK (CSRF/scoping neatins)
5. Cai de eroare? ISSUE N/A ISSUE (F3 /sterge bare-flash, F4 corectie succes)
6. Risc deploy? ISSUE N/A ISSUE (F7 error rows pierd retry)
Constatari Eng (verificate pe cod real)
- F7 (CRITICAL, top risk) [VERIFICAT]: consolidarea pe
/corecteazascoate retry-ul pentru randurierror._CORECTABILE=(needs_data,needs_mapping);post_corectieda 403 peerror(routes.py:974).errorse re-pune DOAR prin/repune(_GESTIONABILE_WEB). In pluserrornu eeditabil-> nu are deloc formular de corectie. „Un singur buton" + Non-Goals (fara backend) sunt in conflict. → POARTA FINALA (taste, dar e corectitudine). - F1 (CRITICAL) [VERIFICAT]:
tests/test_web_detaliu_inline.py+tests/test_acasa_trimiteri.py:71asserteaza markup/JS sterse (detaliu-rand, aria-expanded, #trimitere-detaliu). Nelistate in niciun US.pytest -qnu poate trece. → auto: adauga-le in scope US-002/003 + AC „niciun template/test nu mai refera ID-urile sterse". - F2 (CRITICAL):
<script>inline din_trimitere_detaliu.html:161-176cheamamarcheazaDetaliuDeschis(sters) +scrollIntoViewpe randul de fundal -> TypeError dupa swap in modal. → auto: rescrie scriptul fragmentului pentru modal. - F3 (HIGH):
/stergeintoarce bare-flash; in modal lasa overlay blocat. → auto: AC modal se inchide pe succes sterge (listener petrimiteriChanged). - F4 (HIGH): succes corectie fara mecanism de inchidere/AC. → auto: pe succes (queued) modalul se inchide +
trimiteriChangedreincarca lista. - F5 (HIGH): poll-pause pe „bifa exista" se poate bloca permanent daca randul bifat paraseste filtrul. → auto: pauza DOAR pe trigger periodic
every 15s;trimiteriChanged/submit filtru trec; resume pe checkbox change. - F6 (HIGH): D2 — eticheta umana pe rand; reutilizeaza
motiv_uman/eticheta_scurta(NU adaugacod_eroare_dincare re-parseaza acelasi JSON — DRY). Cod brut in modal dinparse_erori(...)[0]['cod']. - F8 (MED): in modal foloseste
prez.cod_rar(fallback „nemapat"), nuprez.cod(care cade pe cod_op_service intern). - F9 (MED):
inertpe ancestor stabil (<main>), nu pe#submissions-wrap(swap target). - F10 (MED): sterge logica toggle (re-click inchide) din
htmx:beforeRequest; test keyboard Enter/Space deschide modal, Esc readuce focus. - F11 (MED): stergerea chevron-ului scoate SINGURA regula touch 44px (
@media pointer:coarse .chevron). → auto: regula min-height/padding 44px pe rand; scopare.tablewrapsa nu strice cardurile 5.8.tabel-trimiteri. - F12 (LOW):
_submission_row_viewdeja intoarcemotivnerandat — reutilizeaza-l pentru eticheta umana (evita al 3-lea decoder).
Cross-Phase Themes
- Tema A — Contradictia D2 (cod brut vs eticheta umana): semnalata independent in Design F3 SI Eng F6. Semnal de incredere ridicat. → rezolvat de POARTA D2 (eticheta umana pe rand).
- Tema B — Coregrafia succes/eroare in modal (close-vs-reload): Design F2 SI Eng F3/F4. → auto: modalul se inchide pe succes (corectie/sterge) +
trimiteriChanged.
Decision Audit Trail
| # | Faza | Decizie | Clasificare | Principiu | Rationament |
|---|---|---|---|---|---|
| 1 | CEO | Pastram modalul (nu doar poll-pause) | Premise gate | utilizator | D3: decizie 2026-06-24 sustinuta; poll-pause inclus via US-005 |
| 2 | CEO | Responsive ramane in 5.9 (toate 8) | Premise gate | utilizator | D1: risc F5/F6 acceptat constient |
| 3 | CEO | Eticheta umana sub pill (nu cod brut) | Premise gate | utilizator | D2: consistent cu investitia 5.4; cod brut in modal |
| 4 | Eng | Reutilizeaza motiv_uman/eticheta_scurta, NU cod_eroare_din nou | Mechanical | P4 DRY | exista deja 2 decodoare rar_error; al 3-lea = duplicare |
| 5 | Eng | Adauga test_web_detaliu_inline.py + test_acasa_trimiteri.py in scope | Mechanical | P1 | altfel pytest nu trece (verificat) |
| 6 | Eng | Rescrie scriptul inline din _trimitere_detaliu.html | Mechanical | P1 | TypeError pe marcheazaDetaliuDeschis sters |
| 7 | Eng | Modal se inchide pe succes corectie+sterge (trimiteriChanged) | Taste->auto | P5/P1 | rezolva close-vs-reload + bare-flash strand |
| 8 | Eng | Poll-pause doar pe trigger periodic; resume pe checkbox change | Mechanical | P5 | evita blocaj permanent (F5) |
| 9 | Eng | modal foloseste prez.cod_rar (nu prez.cod) | Mechanical | P5 | consistent cu tabelul; nemapat -> „—" |
| 10 | Eng | inert pe , nu pe #submissions-wrap | Mechanical | P5 | swap target ar pierde inert |
| 11 | Eng | regula touch 44px pe rand inlocuieste chevron | Mechanical | P1 | chevron (singura regula 44px) e sters |
| 12 | Design | AC ordine verticala modal (motiv->fix->actiuni->tehnic colapsat) | Mechanical | P1/P5 | altfel se reproduce „zidul" de campuri |
| 13 | Design | Buton Sterge pe rand separat (nu margin-left:auto), primar --accent | Mechanical | P5 | margin-left:auto se prabuseste pe mobil |
| 14 | Design | A11y: focus dupa swap + inert&aria-hidden + aria-labelledby + x aria-label | Mechanical | P1 | completeaza pattern-ul dialog |
| 15 | Design | Card-vs-scroll decis in PRD: actionabile=card, dense read-only=scroll | Mechanical | P3 | actionabilele nu trebuie sa ascunda controale |
| 16 | DX | Faza 3.5 sarita | Mechanical | — | fara scope developer-facing (UI operator, backend neatins) |
REVIZUIRI OBLIGATORII (din review — de aplicat la executie)
Aprobat 2026-06-24. Acestea modifica AC-urile din §3; au prioritate unde difera de textul original.
- R1 (US-001/002, din D2+EngF6/DesignF3): sub pill apare o eticheta umana scurta, NU codul brut. Reutilizeaza
motiv_uman/eticheta_scurta(deja inlabels.py;_submission_row_viewdeja intoarcemotivnerandat — randeaza-l). NU adaugacod_eroare_dincare re-parseaza acelasi JSON. Codul brut de catalog ramane DOAR in modal, derivat dinparse_erori(...)[0]['cod']. Redenumeste testele (test_eticheta_umana_sub_pill). - R2 (US-004, din D4): buton primar conditionat de stare —
error-> „Re-pune in coada" (/repune, neschimbat);needs_data/needs_mapping-> „Salveaza si retrimite" (/corecteaza). Un singur buton primar per stare. Teste: retry-fara-editare pe needs_data ramane idempotent-echivalent; retry pe error functioneaza (/repune). - R3 (US-002/003, din EngF1): adauga in scope
tests/test_web_detaliu_inline.py(rescrie/sterge) sitests/test_acasa_trimiteri.py:71(scoate assert#trimitere-detaliu). AC nou: niciun template/test nu mai referatr.detaliu-rand/#trimitere-detaliu/marcheazaDetaliuDeschis/aria-expandedpe rand. - R4 (US-004, din EngF2): rescrie
<script>-ul inline din_trimitere_detaliu.html:161-176pentru modal — faramarcheazaDetaliuDeschis, farascrollIntoViewpe randul de fundal; muta focusul in corpul modalului. - R5 (US-003/004, din EngF3/F4 + DesignF2, Tema B): pe succes corectie SI sterge, modalul se inchide + listener pe
HX-Trigger: trimiteriChangedreincarca lista. Pe load-error al fragmentului: stare „Nu s-a putut incarca [Reincearca]/[Inchide]" (HTMXresponseError), nu placeholder blocat. Disable-on-submit pe toate cele 3 forme (corectie/sterge/mapare). - R6 (US-005, din EngF5): poll-pause scopat DOAR pe trigger periodic
every 15s;trimiteriChangedsi submit-ul de filtru trec mereu. Resume pe checkboxchange->gol via delegare pe body. Test: bifa +trimiteriChangedinca reincarca. - R7 (US-003, din EngF9 + DesignF5):
inertpe ancestor stabil (<main>), NU pe#submissions-wrap. A11y: focus dupa fiecare swap in modal (primul camparia-invalid, altfel heading);inertSIaria-hiddenpe fundal; dialogaria-labelledbyheading; butonxcuaria-label. - R8 (US-002, din EngF11 + EngF10): regula touch
min-height/padding >=44pxpe rand inlocuieste@media pointer:coarse .chevron. Sterge logica toggle (re-click inchide) dinhtmx:beforeRequest. Rand:aria-haspopup="dialog", scoatearia-expanded; pastreaza hover/focus ca afordanta. Test keyboard Enter/Space deschide modal + Esc readuce focus. - R9 (US-004, din EngF8 + DesignF7): operatie+cod in modal foloseste
prez.cod_rar(fallback „nemapat"), nuprez.cod. Candnemapate_inline: linia „Operatie: X · nemapat" urmata de picker; dupa mapare, re-render arata codul rezolvat. - R10 (US-004, din DesignF1): ordine verticala modal: (1) header
#id+pill+motiv uman; (2) bloc eroare blocanta cand exista; (3) mapare inline candnemapate_inline; (4) formular editabil (Nr. rand propriu, VIN dedesubt, apoi grila), cu operatie+cod read-only deasupra campurilor; (5) actiuni (primar, apoi Sterge separat); (6)<details>„Detalii tehnice" (colapsat) cu Nr. prezentare RAR, Cod HTTP, Reincercari, timestamps, mesaj RAR brut + cod brut. Context read-only NU precede formularul. - R11 (US-004, din DesignF4): Sterge pe rand separat (nu
margin-left:auto), gap vizibil, full-width stivuit pe mobil; AC care fixeaza primarul pe--accentumplut si Sterge pe outline distructiv;hx-confirmspecific („Stergi definitiv trimiterea #{id}? Nu se poate anula."). - R12 (US-007, din DesignF6): politica per-tabel decisa AICI — tabele actionabile (Mapari) = card (adauga
data-etichetala<td>-uri, listeaza in Fisiere); dense read-only (Jurnal, Nomenclator) = scroll contained. Scopare.tablewrapsa nu atinga blocul.tabel-trimiteri @media(max-width:767px)din 5.8; test ca acele carduri supravietuiesc.
STATUS: APROBAT (auto-decizii + D1-D4 utilizator). Restore: vezi comentariul din capul fisierului.