8 stories TDD (echipa Sonnet, lead orchestreaza). US-001 scoate hold-ul auto_send din mapare (has_no_auto_send->False, simbol pastrat; cod rezolvat->queued). US-002 scoate bifa auto_send din UI. US-003 preview pas 3 in format .tabel-trimiteri (STARI_PREVIEW + nota_umana_preview, fara repr Python; view-model prez). US-004 filtre layout/stil ca referinta + buton Custom. US-005 navigatie Trimiteri/Mapari sub contoare pe toate paginile. US-006 import <details> nativ colapsabil. US-007 post-commit reveal (OOB _coada/_status + HX-Trigger). US-008 auto-refresh dupa actiuni (nudge eliminat). VERIFY context curat PASS (8/8). /code-review high: 3 buguri reparate (tab nav la self-refresh, pill Custom valori stale, nota_umana_preview precedenta needs_mapping). 934 passed, 1 skipped. Backend trimitere + schema NEATINSE. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
41 KiB
PRD 5.11 — Import compact + preview in format Trimiteri + navigatie + simplificare auto_send
Stare: inchis (2026-06-26 — verify-pass + code-review; vezi RAPORT VERIFY si RAPORT AUTOPLAN)
Proces complet:
docs/ROADMAP.md§5. Contractul RAR (sursa de adevar de contract):docs/api-rar-contract.md. Starea trece:draft → aprobat → in-executie → verify-pass → inchis(actualizata de lead). Acest PRD nu repeta strategia/contractul — le linkeaza.
1. Obiectiv
Reparam un set de bug-uri si frictiuni UX descoperite la dogfooding pe o baza goala (prima
utilizare), confirmate in browser (E2E Playwright pe prezentari_test.csv):
- Dupa primul import ramai blocat — wizard-ul se reseteaza la pasul 1, mesajul „vezi mai jos in
Trimiterile tale" trimite la o sectiune care nu exista in DOM la first-run (
trimiteri-sectionabsent), iar lista nu apare fara reload manual. - Navigatie infundata — din
?tab=mapari/?tab=jurnal(si Cont/Integrare/Nomenclator) nu exista niciun link inapoi la Trimiteri; logo-ul nu e link; meniul hamburger nu are „Trimiteri". - Tabelul de preview (pasul 3) e neingrijit — overflow orizontal taie coloanele Verificat?/Actiuni
(butonul Editeaza), formularul de editare inline se taie, coloana „Note" scapa un repr Python brut
(
[{'cod_op_service': ...}]) iar „Stare" arata coduri brute (needs_mapping/needs_data). auto_send=0produce o stare falsa — un rand mapat (ex. OE-2) apare caneeds_mappingcu mesaj tehnic („cod mapat cu auto_send=0…") si fara actiune; bifa „In coada automat" adauga complexitate si confuzie. Decizie utilizator (2026-06-26): scoatem complet conceptul auto_send din UI.- Randul de filtre arata neuniform — pill-urile au stil outline diferit de butonul solid Filtreaza si stau in dreapta lui; la hover deveneau rosu plin si textul devenea ilizibil.
- Wizard-ul de import ocupa tot ecranul — stepper + upload sunt doua carduri mari stivuite.
Toate sunt UI/UX + o simplificare de mapare (auto_send). Backendul de trimitere (worker, masina de
stari de trimitere, idempotenta, contract RAR) ramane neatins, cu o singura exceptie controlata:
logica de mapare nu mai „tine" randuri pe auto_send (US-001).
2. Non-Goals (anti scope-creep)
- Nu atingem worker-ul, reconcilierea, idempotenta sau contractul RAR.
- Nu schimbam canalul API (
POST /v1/prezentari//valideaza) — doar UI web +mapping.py. (Campulauto_senddin payload-ul API, daca exista, ramane acceptat dar ignorat — vezi US-001.) - Nu stergem coloanele DB
operations_mapping.auto_send/operation_text_rules.auto_send(migrare distructiva inutila) — le lasam cu default1si nu le mai citim pentru a tine randuri. - Nu rescriem categoriile de filtrare cu etichetele din referinta (Facturate/Anulate/Diferente etc.)
— pastram categoriile reale autopass (Toate / needs_mapping / needs_data / error). Adoptam doar
layout-ul si stilul vizual din referinta (
image.png). - Nu schimbam fluxul de erori pe 3 niveluri (5.4) — doar consumam helperele existente in preview.
3. Stories atomice
Fiecare story: cea mai mica unitate care lasa sistemul functional. Backend + UI pentru acelasi comportament = 2 stories.
Fisiere+Depinde decomplete (decid paralelizarea).
US-001: Scoate „hold pe auto_send" din logica de mapare (backend)
Ca operator vreau ca o operatie mapata la un cod RAR sa intre direct in coada pentru ca
bifa auto_send introducea o stare needs_mapping falsa si confuza pe randuri deja corecte.
- Depinde de: —
- Fisiere:
app/mapping.py,app/web/routes.py(DOUA puncte:post_mapeaza_inline~1018-1069 parsare formauto_send+ delegarereresolve_account; ramurahas_no_auto_senddinpost_corectie_trimitere~1166 — referinta „~1160-1185" din draft arata gresit catre mapeaza),app/api/v1/import_router.py(importahas_no_auto_send~linia 48, il foloseste in_resolve_row_for_preview~233 — OMIS in draft; vezi AC „nu sterge simbolul"),tests/test_mapping.py,tests/test_web_mapeaza.py,tests/test_t6_auto_send.py+tests/test_text_rule_autosend.py(de sters/rescris — encodeaza invariantul VECHI; vor deveni RED) (~6 fisiere) - Test intai (RED):
tests/test_mapping.py—test_operatie_mapata_intra_in_queued_indiferent_de_autosend,test_regula_text_rezolvata_nu_mai_tine_randul,test_fara_stare_needs_mapping_pe_auto_send_oprit,test_niciun_rand_existent_nu_se_dezgheata(AC dezghet),test_canal_api_auto_send_ignorat_intra_queued(classify_prezentare,mapping_metaauto_send=0 →queued) - Acceptance criteria:
resolve_prestatiiNU mai marcheazaregula_fara_autosend/ nu mai produce ramuraAUTO_SEND_OPRIT; o operatie cu cod rezolvat (mapare exacta SAU regula text) →queued.has_no_auto_sendNU se sterge — se neutralizeaza (return False) si ramane DEFINIT (importat inroutes.py:70SIimport_router.py:48; stergerea simbolului →ImportErrorla load → app nu porneste). „Eliminat" si „intoarce mereu False" NU sunt echivalente: alege a doua.- Toate cele 4 callsite-uri tratate: clasificare (
mapping.py~413),reresolve_account(~664 + cheia statreview_manual), corectie (routes.py~1166), preview (import_router.py~233). /trimitere/{id}/mapeaza: dupa mapare, randul cu cod valid trecequeued(nuneeds_mappingcu mesajauto_send); raspuns fara cardul „auto-send oprit".needs_mappingramane DOAR pentru operatii fara cod RAR rezolvat (semantica reala).- Coloanele DB raman;
save_mappingaccepta incaauto_send(default 1) dar valoarea nu mai tine randuri (compat migrare). Niciun rand existent nu se „dezgheata" automat fara actiune. - Randuri legacy
needs_mapping-din-auto_send (cod deja prezent) raman blocate pe test/prod fara afordanta de mapare (_nemapate_pentru_submission~881 intoarce[]). DECIZIE explicita: requeue one-time la deploy (reresolve_accountper cont, acum le trecequeued) SAU documentam corectia inline ca singura iesire. (De notat in raportul VERIFY.)
- Verificare E2E:
POST /trimitere/{id}/mapeazadin panoul de detaliu (browser) → randqueued.
US-002: Scoate bifa „In coada automat" din UI (Mapari + preview + detaliu)
Ca operator vreau sa nu mai vad bifa auto_send nicaieri pentru ca nu mai are efect (US-001) si crea confuzie.
- Depinde de: US-001
- Fisiere:
app/web/templates/_macros.html(macroautosend_toggle),app/web/templates/_mapari.html,app/web/templates/_preview_import.html,app/web/templates/_trimitere_detaliu.html,tests/test_web_mapari.py(~5 fisiere) - Test intai (RED):
tests/test_web_mapari.py—test_mapari_fara_toggle_autosend,test_preview_panou_mapare_fara_autosend,test_detaliu_mapare_inline_fara_autosend - Acceptance criteria:
- Macro-ul
autosend_toggleeliminat (sau golit) si scos din cele 3 sabloane. - Panoul „Operatii de mapat la cod RAR" (preview) si tab-ul Mapari salveaza maparea fara nicio referinta la „In coada automat" / „auto_send".
- Coloana „In coada" din tabelul Mapari operatii salvate + reguli text dispare.
- Niciun text rezidual „auto_send" / „Tine pentru verificare" in sabloane.
- Macro-ul
- Verificare E2E: browser pe
/?tab=mapari+ panoul de mapare din preview — fara bifa.
US-003: Preview pas 3 — format identic cu tabelul Trimiteri (UI)
Ca operator vreau ca tabelul de preview sa arate exact ca lista Trimiteri pentru ca acum scapa text intern brut, taie coloane si formularul de editare.
- Depinde de: —
- Fisiere:
app/web/templates/_preview_import.html,app/web/templates/_preview_rand.html,app/web/templates/base.html(refolosire.tabel-trimiteri+ latimicol-*pt coloanele extra),app/web/payload_view.py(prezentare_din_payloadaccepta dict →row.resolveddirect; OMIS), stratul de adaptare in builderele de preview (app/web/routes.py_web_compute_preview~1851 SIapp/api/v1/import_router.py_resolve_row_for_preview~122) — construieste un view-model tipprez+ traduceresolved_status→eticheta, OMIS in draft,app/web/labels.py(NU reutilizare directa — vezi AC; necesita un map de stari PREVIEW),tests/test_preview_import.py(~6 fisiere) - Test intai (RED):
tests/test_preview_import.py—test_preview_nu_contine_repr_python(fixture cu randneeds_mapping/unmapped REAL — altfel trece in gol),test_preview_stare_eticheta_umana(acoperaok/needs_review/already_sent/duplicate_in_file),test_preview_foloseste_clasa_tabel_trimiteri - Acceptance criteria:
- NU reutiliza
eticheta_stare/eticheta_scurtadirect: ridicaKeyErrorpe starile de preview (ok/needs_review/already_sent/duplicate_in_file— absente inSTARI_SUBMISSION). Adauga un map de stari preview→eticheta umana (extindelabels.pysau map nou), inclusiv text pentrualready_sent/duplicate_in_file. - NU pasa
row.errors(lista Python) inmotiv_uman/parse_erori(asteapta string JSON →str()+json.loadsesueaza → fallbackraw[:160]= ACELASI repr pe care US-003 il repara). Stratul de adaptare serializeaza erorile (json.dumps) sau formateaza uman inainte de render. - Tabelul de preview foloseste
.tabel-trimiteri, fara overflow la 1280px (scrollWidth <= clientWidth). Necesita:data-etichetape TOATE celulele (carduri <768px le citesc viatd::before) + latimicol-*pt cele 4 coloane extra (Verificat?/Actiuni/Note/etc.) subtable-layout:fixed. - Coloana „Note" → mesaj uman, niciodata repr Python (
[{'cod_op_service': ...}]). - „Stare" → pill uman (ca la Trimiteri), nu cod brut
needs_mapping/needs_data. - Vehicul (nr + VIN sub), operatie (+ cod RAR sub) randate via view-model
prez(dinpayload_view). - Formularul inline
colspane full-width sub rand dar IESE din grilatable-layout:fixed(randdisplay:blocksau editor in afara tabelului fix), cu Salveaza/Anuleaza mereu vizibile. - Stare „filtrat la zero" (filter JS din
_preview_import.htmlascunde toate randurile) afiseaza un mesaj, nu tabel gol mut; filtrul coexista cu carduriletd{display:block}.
- NU reutiliza
- Verificare E2E: browser pasul 3 — coloane intregi, fara repr brut, editare necliata, mobil + desktop.
US-004: Randul de filtre Trimiteri — layout + stil ca referinta (UI)
Ca operator vreau un rand de filtre uniform si lizibil pentru ca pill-urile aveau alt stil decat butonul Filtreaza, stateau in dreapta si la hover deveneau rosu ilizibil.
- Depinde de: —
- Fisiere:
app/web/templates/_coada.html,app/web/templates/_pills.html,app/web/templates/base.html(CSS.pill-cat+ hover + layout),tests/test_web_filtre.py(~4 fisiere) - Test intai (RED):
tests/test_web_filtre.py—test_pill_uri_in_stanga_controalelor,test_pill_categorie_stil_uniform,test_quick_pills_data_seteaza_interval - Acceptance criteria:
- Layout ca
image.png: pill-uri rapide de data (Azi / 7 zile / 30 zile / Custom) in STANGA, camp de cautare la mijloc, pill-uri de stare cu contoare la dreapta — un singur stil de pill. - Pill-urile NU mai stau
margin-left:autoizolate la dreapta butonului. - Stare activa, dezambiguizata: pill-ul „Toate" (reset) =
--accentplin; pill-urile de CATEGORIE = culoarea lor de categorie cand sunt active (NU toate accent — „accent plin" din draft contrazice schema per-categorie din_pills.html). Enumera token-ul de prim-plan per categorie ca sa garantezi AA, SAU foloseste o pereche fixa (alb pe saturat) cu valori verificate. - Hover lizibil, regula explicita: hover =
background:color-mix(in srgb, currentColor 12%, transparent)(nufilter:brightnessactual, nu rosu plin); pill-ul ACTIV suprima hover-ul. Acelasi mecanism pe reset si pe categorie. - Focus pastrat: inelul
:focus-visible(outline accent) ramane pe toate cele 3 variante de pill dupa rescrierea CSS (US-004 atinge exact acest bloc — usor de pierdut). - Quick-pills de data seteaza
data_de/data_pana(preset) si reincarca lista (HTMX), pastrand pill-ul de stare activ. - Functioneaza in Light/Dark/Petrol cu token-uri concrete enumerate (nu „verifica AA" abstract).
- Layout ca
- Verificare E2E: browser — comutare quick-pill data + stare, hover citibil pe toate temele.
US-005: Link-uri de navigatie sub contoare pe toate paginile (UI)
Ca operator vreau sa ajung oricand inapoi la Trimiteri / Mapari pentru ca din Mapari/Jurnal nu mai aveam cale de intoarcere.
- Depinde de: —
- Fisiere:
app/web/templates/base.html(header +#cont-menu), AMBELEdashboard.htmlSI_status.html(ambele randeaza<div id="status-bar">— pe cai diferite: full-page vs OOB/partial; „sau" din draft risca nav prezenta la load dar pierduta la refresh + duplicat de id),tests/test_web_nav.py(~3 fisiere) - Test intai (RED):
tests/test_web_nav.py—test_nav_trimiteri_mapari_pe_mapari,test_nav_trimiteri_pe_jurnal,test_logo_linkeaza_acasa - Acceptance criteria:
- Sub contoarele din
#status-bar, pe FIECARE pagina (acasa/mapari/jurnal/cont/integrare/ nomenclator): rand de link-uriTrimiteri+Mapari(cu badge needs_mapping daca exista), cu marcaj activ pe pagina curenta. Sursa marcajului activ = o variabila de context numita explicit (ex.tab_activ, comparata cu?tab=), nu ghicita de implementator. - Badge-ul
needs_mappingreutilizeaza O SINGURA sursa (acelasi camp ca_mapari_badgedin hamburger /blocate_total), nu un al doilea contor calculat diferit. - Logo-ul ROMFAST + titlul linkeaza la
/(Trimiteri). - Meniul hamburger capata si „Trimiteri" (Acasa) ca prima intrare.
- Niciun deadlock: din orice tab se ajunge la Trimiteri intr-un click.
- Sub contoarele din
- Verificare E2E: browser — din Mapari si Jurnal, un click → Trimiteri.
US-006: Import = container compact colapsabil (UI)
Ca operator vreau ca importul sa nu ocupe tot ecranul pentru ca stepper-ul + upload-ul mare stau in cale dupa ce am deja trimiteri.
- Depinde de: —
- Fisiere:
app/web/templates/_acasa.html,app/web/templates/_upload.html,app/web/templates/_stepper.html,app/web/templates/base.html(CSS/JS accordion),tests/test_web_acasa.py(~4 fisiere) - Test intai (RED):
tests/test_web_acasa.py—test_import_colapsat_cand_are_trimiteri,test_import_deschis_la_first_run - Acceptance criteria:
- Stepper + upload intr-UN singur container („Importa un fisier"), nu doua carduri.
- Colapsat implicit cand contul are deja trimiteri (
are_trimiteri=True); auto-deschis la first-run (are_trimiteri=False). - In timpul fluxului (mapcoloane/preview) containerul ramane deschis (nu se inchide intre pasi).
- Implementare cu
<details>nativ (disclosure CSS-only): serverul seteaza atributulopendinare_trimiteri, deci „fara JS → degradare la deschis" si „colapsat la returning" sunt ambele corecte fara toggle JS (un toggle JS pur ar lasa returning-user-ul fara-JS cu ecranul permanent deschis = exact bug-ul reparat).aria-expanded/focus pastrate. - Ordinea de stivuire definita pe cele 4 combinatii (
are_creds×are_trimiteri) — accordion, „Primii pasi",trimiteri-sectionnu se suprapun la first-run-cu-creds.
- Verificare E2E: browser — first-run deschis; dupa ce exista trimiteri, colapsat; click → extins.
US-007: Dupa commit, lista Trimiteri apare + se reimprospateaza automat (UI + glue)
Ca operator vreau sa-mi vad trimiterile imediat dupa import pentru ca acum mesajul trimite la o sectiune inexistenta si nimic nu se actualizeaza fara reload.
- Depinde de: US-006
- Fisiere:
app/web/routes.py(web_confirma_import~2757 intoarce AZI doar_upload.htmlviahx-target=#import-section, outerHTML— un swapouterHTMLpe#import-sectionNU poate materializa un frate#trimiteri-section; alege mecanismul de dezvaluire — vezi AC),app/web/templates/_upload.html,app/web/templates/_acasa.html,app/web/templates/_coada.html,app/web/templates/_status.html+dashboard.html(OOB pe#status-bar— e in afara luiacasa-section, nu se actualizeaza la re-randarea_acasa/_upload),tests/test_import_commit.py(~6 fisiere) - Test intai (RED):
tests/test_import_commit.py—test_commit_raspuns_contine_trimiteri_section,test_commit_raspuns_seteaza_hx_trigger_trimiteriChanged(asertie pe header literal),test_first_run_dupa_commit_arata_lista,test_commit_actualizeaza_status_bar(OOB contoare) - Acceptance criteria:
- Mecanism de dezvaluire ales explicit: fie (a) re-randam
_acasa.htmlcomplet si retargetam pe#acasa-section, fie (b) emitem un OOB swap care injecteaza_coada.html. Minimal fata de codul actual (return_upload.html-only) = (b). La first-run#submissions-wrapproaspat injectat isi declanseaza singurhx-trigger="load". - Raspunsul seteaza
HX-Trigger: trimiteriChanged(lipseste azi pe confirma; cf.post_mapeaza_inline:1066) — altfel la returning-user (sectiune deja in DOM) randurile noiqueuednu apar. Atentie la dublu-load daca re-randam si_acasa(inofensiv, de notat). - Containerul de import se colapseaza, iar lista Trimiteri se reincarca automat si arata randurile.
- Contoarele
#status-barse actualizeaza via OOB swap (sunt in_status.html/dashboard.html, in afaraacasa-section— re-randarea_acasanu le atinge), imediat, nu la poll-ul de 15s. - Mesajul de succes ramane onest („S-au pus in coada N prezentari") si pointeaza la o sectiune care chiar exista.
- Mecanism de dezvaluire ales explicit: fie (a) re-randam
- Verificare E2E: browser, baza goala — import → commit → lista apare + contoare actualizate, fara reload.
US-008: Auto-refresh dupa actiuni, fara „Reincarca" manual (UI)
Ca operator vreau ca lista sa se actualizeze singura dupa ce actionez pentru ca butonul manual „Reincarca" (nudge „Date noi") trecea neobservat (ex. dupa ce am mapat un cod si s-a trimis la RAR).
- Depinde de: US-007
- Fisiere:
app/web/templates/base.html(JS poller/nudge),app/web/templates/_coada.html,app/web/templates/_submissions.html,tests/test_web_refresh.py(~3 fisiere) - Test intai (RED):
tests/test_web_refresh.py—test_actiune_proprie_reincarca_automat,test_nudge_nu_mai_blocheaza_actualizarea - Acceptance criteria:
- Dupa o actiune proprie (mapare inline, corectie, repune, commit import) lista se reincarca automat (fara click pe „Reincarca").
- Poll-ul de fundal: cand detecteaza date noi declansate de actiuni proprii, aplica refresh automat; nudge-ul manual ramane doar pentru schimbari externe (alt proces/worker) — sau se elimina daca devine redundant. (Decizie de implementare documentata in raport.)
- Nu se reseteaza filtrul/pagina curenta la auto-refresh (pastreaza
#filtre-trimiteri).
- Verificare E2E: browser — mapare inline a unui cod → randul devine
queued/sentfara click manual.
4. Riscuri
- R1 — Scoaterea auto_send rastoarna „default-ul de siguranta CEO" (reguli text / mapari tineau randul
pentru verificare). Acceptat constient de utilizator (2026-06-26): mapped → queued direct. Mitigare:
randurile genuin nemapate raman
needs_mapping(nu pleaca), iar preview-ul are gate per-rand („Verificat?") inainte de commit. Documentam in CLAUDE.md (invariantul auto_send) ca a fost retras. - R2 — Preview in format Trimiteri: tabelul Trimiteri presupune un view-model (vehicul/op/cod RAR);
randurile de preview vin din alt drum (
_resolve_row_for_preview). Risc de divergenta de campuri. Mitigare: refolosimpayload_view/labelsca pe canalul Trimiteri; test anti-repr. - R3 — Accordion + HTMX: colapsarea nu trebuie sa ascunda pasii in timpul fluxului mapcoloane/preview.
Mitigare: container deschis cat timp
import-sectionrandeaza un pas != upload slim; test dedicat. - R4 — Regresie tabel:
.tabel-trimiteriare reguli responsive (carduri <768px) — preview-ul are coloane diferite (Verificat?/Actiuni). Mitigare: verificare E2E mobil + desktop.
5. Intrebari deschise
Rezolvate cu utilizatorul la planificare (2026-06-26) — vezi raspunsurile incorporate mai sus: Q1 filtre = layout complet ca referinta + fix hover lizibil; Q2 preview = format ca Trimiteri; Q3 = scoatem complet bifa auto_send (Mapari + Trimiteri); Q4 = acordeon compact + lista apare/ refresh automat dupa commit + link-uri Trimiteri/Mapari sub contoare.
- (rezolvat) Pastram coloanele DB
auto_send? → DA, default 1, ne-citite pentru hold (non-distructiv). - (deschis, minor) Nudge-ul „Date noi" pentru schimbari externe: il pastram redus sau il eliminam? → decizie la implementare (US-008), documentata in raport.
6. Valuri de executie (graful de dependente)
Val 1 (paralel, fisiere disjuncte):
[US-001] mapping.py + routes mapeaza (backend)
[US-003] preview format Trimiteri (_preview_*.html, base.css)
[US-004] filtre layout+stil+hover (_coada/_pills/base.css)
[US-005] navigatie sub contoare (base.html/_status/dashboard)
[US-006] import accordion compact (_acasa/_upload/_stepper)
Val 2 (deblocate de Val 1):
[US-002] scoate toggle auto_send din UI (dep US-001; _macros/_mapari/_preview/_detaliu)
[US-007] post-commit reveal+refresh (dep US-006; routes/_acasa/_upload/_coada)
Val 3:
[US-008] auto-refresh dupa actiuni (dep US-007; base.js/_coada/_submissions)
Atentie la fisiere fierbinti partajate intre stories (serializare de catre lead):
base.html (US-004 CSS, US-005 header/menu, US-006 accordion JS) si _coada.html /
_preview_import.html apar in mai multe stories — NU paralel pe acelasi fisier (vezi ROADMAP §5.5).
Raport VERIFY
Completat de subagentul verificator (context curat, 2026-06-26) in faza VERIFY — ROADMAP §5.6. Executie: echipa de teammates Sonnet (lead orchestreaza, NU scrie cod), 6 runde TDD pe valuri cu fisiere disjuncte;
base.html/routes.py/_coada.html/_status.htmlserializate ca fisiere fierbinti.
VERDICT GLOBAL: PASS → verify-pass / CLOSE. 8/8 stories trec criteriile de acceptare, cu dovezi cod + teste + randare runtime (verificatorul a pornit aplicatia reala si a inspectat HTML-ul randat).
- Suita:
python3 -m pytest -q→ 929 passed, 1 skipped (skip =test_live_rar, gated corect pe markerlive+AUTOPASS_LIVE_RAR). Smoke bootpython3 -c "import app.main"→ OK (critic US-001:has_no_auto_sendpastrat → fara ImportError). (Dupa adaugarea testelor cu nomenclatura PRD pe US-008: 931 passed.) - US-001 PASS —
has_no_auto_send→return False(definit + importat in routes.py:72 si import_router.py:48);resolve_prestatiinu mai marcheazaregula_fara_autosend; ramuraAUTO_SEND_OPRITscoasa din classify; cele 4 callsite tratate; canal API auto_send=0 →queued;needs_mappingdoar pt unmapped real; coloane DB raman; teste vechi rescrise (nu sterse). Decizie randuri legacy:reresolve_accountle re-trecequeuedla deploy (documentat). - US-002 PASS — macro
autosend_togglegolit, simbol pastrat; 0 reziduuri auto_send / „In coada automat" in template-uri (grep) + 0 in dashboard-ul randat. - US-003 PASS —
STARI_PREVIEWmap nou inlabels.py(fara KeyError pe stari preview);nota_umana_preview(errors ca lista → fara repr brut); view-modelprezdinpayload_view(accepta dict);.tabel-trimiteri+col-*+data-etichetape toate celulele + editortr.preview-edit(scapa grila fixa) + mesaj „filtrat la zero". - US-004 PASS — quick-pills data STANGA / cautare MIJLOC / pills stare DREAPTA; hover
color-mix(currentColor 12%),:focus-visibleaccent, categorie activa=currentColor, reset=--accent, activ suprima hover. (Nota minora: butonul „Custom" — vezi mai jos.) - US-005 PASS — nav Trimiteri+Mapari in
_status.htmlrandat pe fiecare pagina (dashboard.html incarca fragmentul, fara duplicat de id), activ dintab_activ, badge din sursa unicacounts.needs_mapping; logo+titlu link/; hamburger „Trimiteri" prima. Confirmat runtime (aria-current="page"pe Mapari la?tab=mapari). - US-006 PASS —
<details id="import-details" {open if not are_trimiteri}>nativ (fara toggle JS); runtime: first-runopen+ placeholder#trimiteri-section; returning colapsat + lista plina. - US-007 PASS —
web_confirma_import→_uploadslim + OOB_coada(#trimiteri-section) + OOB_status(#status-bar) + headerHX-Trigger: trimiteriChanged;#submissions-wrapse auto-incarca; mesaj de succes onest catre o sectiune care chiar exista. - US-008 PASS — actiuni proprii emit
trimiteriChanged→ reincarcare; poller comparadata-vsi cheamareincarcaTrimiteri()cuhx-include="#filtre-trimiteri"(pastreaza filtru+pagina); nudge „Date noi" ELIMINAT (decizie documentata: distinctia propriu-vs-extern nu e posibila pe client). - E2E: PROBAT la nivel de aplicatie reala (uvicorn :8011, login sesiune, HTML randat real pentru
accordion/nav/logo/filtre/zero-reziduu auto_send). NEPROBAT: click-through Playwright complet pe
upload→preview→commit si testul live RAR
FINALIZATA(gated, fara creds web in mediu) — acelasi status ca livrabilele anterioare; backend trimitere neatins, risc minim. - Regresia de aur: PASS la nivel de teste —
test_api(POST /v1/prezentari) +test_import_e2e(import→commit→queued) + worker reconcile/rar_errors verzi; worker/idempotenta/build_key/contract RAR NEATINSE (non-goals respectate).
Note minore (non-blocante, follow-up):
- US-004 „Custom": AC enumera 4 quick-pills (Azi/7zile/30zile/Custom); doar 3 randate ca butoane
(JS-ul suporta ramura
'custom', dar fara buton). De adaugat butonul SAU scos „Custom" din AC. - Cod/comentarii vestigiale in
import_router.py(_motiv_clasificareramuraneeds_mapping/auto_send acum inaccesibila; comentarii care inca spun „auto_send gate"). Pur cosmetic.
RAPORT AUTOPLAN
Faza 1 — CEO (strategie & scope)
0A. Provocarea premiselor
- Premisa centrala (US-001): "auto_send hold = stare falsa". Citind
mapping.py:252-254si434-447, hold-ul era un gate de siguranta intentionat, nu un bug. Reformulare onesta: scoatem un gate de siguranta pentru ca frictiunea > riscul de ireversibilitate perceput. GATE PREMISA: utilizatorul a confirmat (2026-06-26) scoaterea completa — premisa acceptata constient, documentata in R1. - Premisa "preview-ul are gate Verificat? care compenseaza" e PARTIALA: gate-ul exista doar pe calea import web; canalul API + remaparea inline (
routes.py:1166) trec direct inqueued. Acceptat de utilizator la gate. - Restul premiselor (overflow tabel, repr Python in Note, hover rosu ilizibil, nav infundata, wizard mare, reveal post-commit rupt) = confirmate in cod (vezi Faza 3).
0B. Ce exista deja (mapare sub-probleme -> cod)
| Sub-problema | Cod existent de refolosit |
|---|---|
| Etichete umane stare/motiv | labels.py: eticheta_stare, motiv_uman, parse_erori |
| Viewmodel rand trimitere | payload_view.py + r.prez.* in _submissions.html |
| Tabel responsive | .tabel-trimiteri + carduri <768px in base.html |
| Pills stare + contoare | _pills.html + filtreazaStare() in base.html |
| Refresh lista | HTMX trimiteriChanged from:body (deja cablat in _coada.html) |
| Sectiune trimiteri | #trimiteri-section exista in _coada.html (doar conditionat de are_trimiteri) |
0C. Dream-state delta
- ACUM: 8 frictiuni de first-run, una mascand o decizie de siguranta ireversibila.
- ACEST PLAN: first-run curat (import -> preview ingrijit -> commit -> lista apare/refresh), nav fara fundaturi, mapare fara concept auto_send.
- IDEAL 12 luni: un E2E smoke de first-run ca poarta de release (codifica scriptul de dogfooding) ca aceste 8 simptome sa nu reapara. Recomandare deferata (vezi TODOS).
0C-bis. Alternative (US-001)
| Abordare | Efort | Risc | Verdict |
|---|---|---|---|
| Scoatere completa (ales) | mic | gate pierdut pe API/inline | ALES de utilizator |
| Hold doar pe text-rules unattended | mic | minim (pastreaza net unde conteaza) | respins de utilizator la gate |
Default per-cont (ca on_unmapped_error_default) |
mediu | reversibil, dar pastreaza complexitate | respins de utilizator |
0D-0F. Mod = SELECTIVE EXPANSION. Premisa confirmata la gate. Procedam.
Voci duale CEO (subagent-only; Codex indisponibil)
CLAUDE SUBAGENT (CEO): 11 constatari. Critice: (F1) US-001 e o decizie clasa-siguranta impachetata cu UX cosmetic — risc de aprobare-prin-asociere; (F6) regret 6 luni = o regula text gresita auto-trimite FINALIZATA terminal nerecuperabil. Hi: F3 (premisa laundering), F4 (mitigare R1 supraevaluata — nu acopera canalul API), F5 (cazul periculos real = text-rules unattended), F8 (alternativa default-per-cont neanalizata), F10 (over-bundling). Recomandare subagent: split US-001/002 din restul. Utilizatorul a ales full removal la gate — F4/F5/F6 raman ca follow-up optional, nu blocant.
CEO DUAL VOICES — CONSENSUS:
Dimensiune Claude Codex Consensus
1. Premise valide? Partial N/A flag (gate trecut de user)
2. Problema corecta? Da N/A confirmat de 1 voce
3. Scope calibrat? Nu(F10) N/A flag (over-bundle, dar waves ok)
4. Alternative explorate? Nu(F8) N/A flag (rezolvat la gate)
5. Riscuri piata/legal acoperite? Partial N/A flag (R1 acceptat)
6. Traiectorie 6 luni sanatoasa? Partial N/A flag (F6 -> TODOS)
Codex = N/A (usage limit). Single-critical din 1 voce = flagat oricum.
NU in scope (confirmat)
Worker / reconciliere / idempotenta / contract RAR / canal API (payload) / coloane DB auto_send (raman, default 1) / categorii filtrare (raman cele reale autopass) / fluxul de erori 3-niveluri.
Registru Erori & Salvare (relevant acestui plan)
| Suprafata | Esec | Salvare existenta |
|---|---|---|
| Import upload | fisier invalid / multi-foaie | eroare_upload / select foaie (_upload.html) |
| Preview rand | cod necunoscut nomenclator | promovat la cod_op_service -> needs_mapping (nu se trimite raw) |
| Commit | rand needs_mapping |
exclus din commit (ramane in lista) |
Sumar CEO
Plan sanatos ca directie. Singurul flag strategic (US-001 fara control compensator pe calea unattended) acceptat constient la gate. US-003-008 = castiguri de first-run cu risc redus; US-007/008 cele mai sigure. Recomandare: pastram PRD-ul unit (waves deja serializeaza fisierele fierbinti), adaugam 1 item TODOS (E2E first-run + control optional text-rule).
Faza 2 — Design (UI scope: DA)
Voci duale Design (subagent-only; Codex indisponibil)
CLAUDE SUBAGENT (design): constatari grounded in template-uri reale.
- F2.4 (CRITIC):
eticheta_stare/eticheta_scurtaridicaKeyErrorpe starile de preview (ok/needs_review/already_sent/duplicate_in_file) — reutilizarea „ca la Trimiteri" crapa preview-ul. → US-003 AC. - F3.1 (CRITIC): „activa = accent plin" contrazice pill-urile colorate per-categorie (
_pills.html:10). Reset = accent; categorie = culoarea ei. → US-004 AC. - F2.1/F2.2/F2.3 (high): celulele de preview n-au
data-eticheta(carduri <768px ilizibile); coloanele extra n-au latimicol-*subtable-layout:fixed; editorulcolspanmosteneste latimea care depaseste. → US-003 AC. - F3.2/F3.3 (high): token-uri de contrast/hover neenumerate per tema/categorie — cel mai mare risc de „haunt". → US-004 AC.
- F2.6 (high): preview n-are view-model
prez; adaptorul lipseste din Fisiere. → US-003 Fisiere. - F4.1/F4.2 (high):
#status-bardefinit in DOUA locuri; variabila de tab activ nenumita. → US-005 Fisiere+AC. - F1.3 (medium): degradarea fara-JS contrazice „colapsat la returning" — necesita
<details>nativ. → US-006 AC.
DESIGN LITMUS — CONSENSUS:
Dimensiune Claude Codex Consensus
1. Ierarhie info (accordion) ok* N/A confirmat (1 voce) *cu state-table
2. Stari lipsa (preview) NU N/A flag CRITIC (F2.4) -> US-003
3. Matrice pill hover/active/focus NU N/A flag CRITIC (F3.1) -> US-004
4. Nav activ + badge Partial N/A flag (F4) -> US-005
5. Specificitate AC Partial N/A flag (token-uri, view-model)
Codex = N/A (usage limit).
Faza 3 — Eng (arhitectura, teste, risc)
Diagrama de dependente (componente noi vs existente)
[import upload] -> _upload.html (#import-section, outerHTML swap)
| US-006: invelit in <details> (open=are_trimiteri)
v
[web_confirma_import ~2757] --returneaza--> _upload.html (AZI: doar atat -> bug US-007)
US-007 fix: + OOB inject _coada.html (#trimiteri-section) + HX-Trigger trimiteriChanged
+ OOB #status-bar (_status.html / dashboard.html)
|
v
[#submissions-wrap] --hx-trigger: load, trimiteriChanged from:body--> /_fragments/submissions
| |
v v
_submissions.html (r.prez view-model) _pills.html (OOB) <- US-004 CSS
[mapping.py resolve_prestatii] --auto_send hold SCOS (US-001)--> status: queued | needs_mapping(real)
has_no_auto_send: NEUTRALIZAT (return False), simbol PASTRAT (importat in routes.py + import_router.py)
callsite-uri: clasificare ~413 | reresolve ~664 | corectie routes ~1166 | preview import_router ~233
[preview builders] _web_compute_preview ~1851 / _resolve_row_for_preview ~122
US-003: + adaptor resolved_status -> eticheta umana + view-model prez (payload_view) + json.dumps(errors)
Voci duale Eng (subagent-only; Codex indisponibil)
CLAUDE SUBAGENT (eng): 13 constatari verificate in cod.
- F1 (HIGH/boot-crash):
import_router.py:48importahas_no_auto_send,:233il foloseste — al 4-lea callsite, OMIS din US-001 Fisiere. Stergerea simbolului →ImportError→ app nu porneste. „Eliminat" ≠ „return False". → US-001. - F4 (HIGH):
test_t6_auto_send.py+test_text_rule_autosend.pyencodeaza holdul vechi → devin RED, neprogramate. → US-001. - F5/F6 (HIGH):
motiv_uman/parse_eroriasteapta string JSON;row.errors(lista) → fallbackraw[:160]= ACELASI repr. Necesita strat de adaptare in buildere. → US-003. - F2 (medium): referinta de linie „~1160-1185" arata gresit; sunt 2 puncte (mapeaza ~1032 form, corectie ~1166). → US-001.
- F3 (medium): randuri legacy needs_mapping-din-auto_send raman fara afordanta (
_nemapate_pentru_submission~881 →[]). → US-001 AC dezghet. - F7 (medium):
payload_view.pynecesar dar omis din US-003 Fisiere. → US-003. - F8/F9/F10 (HIGH): US-007 —
outerHTMLpe#import-sectionnu materializeaza frate#trimiteri-section; lipsesteHX-Trigger;#status-bar(alt fisier) nu se actualizeaza. → US-007. - F11/F13 (low): waves §6 supravand paralelismul pe
base.html(3 stories, regiuni disjuncte → serializate de lead);save_mappingscrie auto_send=0 dupa US-002 (inofensiv cat e ignorat).
ENG DUAL VOICES — CONSENSUS:
Dimensiune Claude Codex Consensus
1. Arhitectura sanatoasa? Da N/A confirmat (1 voce)
2. Acoperire teste suficienta? NU N/A flag (F4 + gap-uri) -> test plan
3. Riscuri performanta? ok N/A nimic flagat (batch lookup already_sent fara N+1)
4. Securitate? ok N/A nimic nou (CSRF/auth neatinse de UI)
5. Cai de eroare tratate? Partial N/A flag (boot-crash F1, KeyError F5/F6)
6. Risc de deploy gestionabil? Partial N/A flag (randuri legacy F3)
Codex = N/A (usage limit).
Test plan (artefact pe disc)
~/.gstack/projects/romfast-rar-autopass/main-5.11-test-plan-20260626.md — 18 codepath-uri mapate la acoperire,
suite de rulat (inclusiv smoke de boot import app.main dupa US-001), 3 gap-uri critice.
Registru moduri de esec (cu flag-uri critice)
| Mod de esec | Trigger | Gravitate | Mitigare in plan |
|---|---|---|---|
| App nu porneste | stergerea has_no_auto_send |
CRITIC | US-001 AC: neutralizare, nu stergere + smoke boot |
| Preview crapa la render | reutilizare eticheta_stare pe stari preview |
CRITIC | US-003 AC: map de stari preview |
| Repr Python reapare in Note | row.errors in motiv_uman |
HIGH | US-003 AC: adaptor json.dumps |
| Returning-user nu vede randuri noi | lipsa HX-Trigger pe confirma |
HIGH | US-007 AC: header trimiteriChanged |
| Randuri legacy blocate fara iesire | needs_mapping-din-auto_send pe prod | MEDIUM | US-001 AC: requeue one-time SAU doc corectie |
Cross-phase themes
- Theme: vocabularul de stari preview ≠ submission — flagat INDEPENDENT in Faza 2 (Design F2.4) si
Faza 3 (Eng F5/F6). Semnal de incredere mare: US-003 nu poate reutiliza direct
labels.py; necesita un strat de traducere + view-model. Cea mai importanta corectie a planului. - Theme: Fisiere sub-dimensionate fata de AC — US-001 (import_router), US-003 (payload_view + buildere), US-007 (_status.html) — toate omiteau fisiere pe care propriile AC le cer. Corectat in stories.
Corectie graf de executie (§6)
Wave 1 NU e complet paralel: base.html e atins de US-004 (CSS pill), US-005 (header/nav), US-006
(<details>) — regiuni disjuncte, dar lead-ul le SERIALIZEAZA (3 edituri pe acelasi fisier). Paralelismul
real al Wave 1 e mai mic decat anunta graful. _coada.html (US-004→007→008) e serializat oricum de dependente.
Deferate la TODOS.md
- E2E smoke de first-run ca poarta de release (CEO F2).
- Control compensator optional pe auto-trimitere unattended (CEO F5/F6) — risc rezidual acceptat de user.
Decision Audit Trail
| # | Faza | Decizie | Clasificare | Principiu | Rationament | Respins |
|---|---|---|---|---|---|---|
| 1 | CEO | Premisa auto_send: full removal | GATE (user) | — | Utilizatorul a confirmat la gate | hold text-rule-only; default per-cont |
| 2 | CEO | Pastram PRD unit (nu split US-001/002) | Taste | P3/P6 | Waves serializeaza deja; pre-launch, risc real ~0 | split in 2 PRD-uri (subagent F1/F10) |
| 3 | CEO | E2E first-run -> TODOS, nu in scope acum | Mechanical | P3 | Boil-lake separat, nu blocheaza 5.11 | inclus in 5.11 |
| 4 | Eng | US-001: neutralizare has_no_auto_send, NU stergere | Mechanical | P5 | Stergerea = ImportError (import_router) = boot crash | stergere simbol |
| 5 | Eng | US-001 Fisiere += import_router.py + teste vechi | Mechanical | P1/P2 | Callsite real + teste care devin RED | lasa Fisiere ca-n draft |
| 6 | Eng | US-001: randuri legacy -> decizie requeue/doc | Taste | P1 | In blast radius; impact pe prod DB | ignora (lasa blocate tacit) |
| 7 | Design+Eng | US-003: strat adaptare + map stari preview | Mechanical | P1 | Reutilizare directa crapa/repr — cross-phase theme | reutilizare directa labels |
| 8 | Design+Eng | US-003 Fisiere += payload_view + buildere | Mechanical | P1/P2 | AC cere view-model prez inexistent pe calea preview | doar template+labels |
| 9 | Design | US-003: data-eticheta + col-* + colspan escape | Mechanical | P1 | Altfel overflow/mobil rup (AC propriu) | doar clasa .tabel-trimiteri |
| 10 | Design | US-004: reset=accent, categorie=culoare proprie | Mechanical | P5 | „accent plin" contrazice schema per-categorie | toate accent |
| 11 | Design | US-004: token-uri hover/active/focus enumerate | Mechanical | P1/P5 | „verifica AA" abstract = haunt | lasa la implementator |
| 12 | Design | US-005: AMBELE status-bar + var tab_activ | Mechanical | P5 | „sau" risca nav pierduta la refresh + dup id | un singur fisier |
| 13 | Design | US-006: <details> nativ |
Mechanical | P5 | Toggle JS pur rupe degradarea fara-JS | toggle JS |
| 14 | Eng | US-007: OOB inject _coada + HX-Trigger + OOB status-bar | Mechanical | P1/P5 | outerHTML nu materializeaza frate; lipsa trigger | „include/dezvaluie" vag |
Stare review
- Faza 1 CEO: rulat (subagent-only). Premisa confirmata la gate.
- Faza 2 Design: rulat (subagent-only). 2 critice -> AC corectate.
- Faza 3 Eng: rulat (subagent-only). 1 boot-crash + cross-phase theme -> stories corectate.
- Faza 3.5 DX: SARIT — fara suprafata developer-facing (planul exclude canalul API; UI = operator).
- Codex: indisponibil toata sesiunea (usage limit pana Jul 18) -> toate vocile = subagent-only.