Copiază COMPLET un website extern în Symbai (magazin online / site de prezentare) — toate paginile, tot catalogul cu poze/descrieri/categorii/variante, blogul, paginile legale — printr-un proces care rulează ORE, descompus în sarcini mici verificate, care NU se oprește la 20% și NU declară „gata" până nu e verificat obiectiv. Folosește la „copiază-mi site-ul / magazinul", „adu-mi site-ul de pe X în Symbai", „clonează magazinul de pe Y", „importă tot site-ul meu", „mută-mă de pe vechiul magazin", „fă-mi site-ul identic cu cel vechi", „copiază toate produsele de pe site-ul meu", „de ce ai copiat doar o parte din site", „continuă copierea site-ului". Pentru un site MIC sau o singură pagină de prezentare (fără catalog mare) poți folosi direct `construieste-website`; pentru cataloage mari / site întreg / „să nu se mai oprească până nu termină" folosește ACEST skill.
Instrucciones de origen · Vista previa de solo lectura
name
copiaza-website
description
Copiază COMPLET un website extern în Symbai (magazin online / site de prezentare) — toate paginile, tot catalogul cu poze/descrieri/categorii/variante, blogul, paginile legale — printr-un proces care rulează ORE, descompus în sarcini mici verificate, care NU se oprește la 20% și NU declară „gata" până nu e verificat obiectiv. Folosește la „copiază-mi site-ul / magazinul", „adu-mi site-ul de pe X în Symbai", „clonează magazinul de pe Y", „importă tot site-ul meu", „mută-mă de pe vechiul magazin", „fă-mi site-ul identic cu cel vechi", „copiază toate produsele de pe site-ul meu", „de ce ai copiat doar o parte din site", „continuă copierea site-ului". Pentru un site MIC sau o singură pagină de prezentare (fără catalog mare) poți folosi direct `construieste-website`; pentru cataloage mari / site întreg / „să nu se mai oprească până nu termină" folosește ACEST skill.
Copiază un website complet în Symbai — hands-free, pe ore, verificat
Proprietarul vrea site-ul lui (sau unul pe care îl deține/administrează) copiat întreg în Symbai: nu o aproximare de homepage, ci tot catalogul, toate categoriile, pozele, descrierile, blogul, paginile legale. Pe site-uri mari asta durează ore și NU încape într-o singură „tură" de agent. Acest skill e un orchestrator care duce treaba la capăt fără să se oprească la 20% și fără să mintă că e gata.
De ce era nevoie de el:analyze_external_website vede maxim 24 de pagini și nu citește sitemap-ul → pe un site de mii de produse copiezi ~20% și pari „gata". Aici pornim de la scopul ADEVĂRAT al site-ului (numitor independent), ținem o coadă durabilă pe disc (supraviețuiește compactării contextului), lucrăm pe loturi mici cu sub-agenți, și declarăm „gata" doar când o poartă de paritate obiectivă (ID-uri lipsă = 0) trece.
../construieste-website/SKILL.md — EXECUTORUL (cum scrii efectiv în Symbai: produse, categorii, hero, footer, PDP). Acest skill îl ORCHESTREAZĂ.
../../knowledge/website-copy-intake.md + ../../knowledge/website-builder-pdp.md — paritate vizuală + pagina de produs bogată.
Două benzi: seed rapid din Setări + perfecționare fidelă cu agentul
Există acum două căi complementare, nu două implementări concurente:
Seed rapid self-service (mecanic): în Symbai, Setări → General → Date & Mentenanță → Import website public. Managerul selectează brandul/unitatea, scrie URL-ul și parola Symbai de import, apoi confirmă că reprezintă brandul sau are permisiunea de copiere. Serverul face crawl + cache + produse + galerii locale + arbore de categorii + blog draft + pagini builder native, în job persistent. Browserul și laptopul pot fi închise. Aceasta este calea recomandată pentru onboarding rapid.
Perfecționare fidelă (judecată): acest skill preia jobul ajuns la review_required, rulează/remediază porțile, construiește design-plan.json, verifică vizual desktop+mobil, mapează variante/formulare/video și aprobă textele legale. Aici rămân utile bucla, verificatorul adversarial și, doar la cerere explicită, agentul programat.
Seed-ul automat este intenționat oprit înainte de cutover. Nu activează meniul importat, nu schimbă website-ul implicit, nu publică textele legale și nu scrie 301-urile până când:
un om confirmă verificarea vizuală și, separat, verificarea legală;
clone_audit_all(...).data.pass === true;
audit_shop_health(...).data.ok === true.
Parola din formular NU este parola site-ului sursă. Este cheia server-side Symbai (WEBSITE_IMPORT_PASSWORD; fallback separat doar în development), comparată constant-time, cu rate-limit. Nu se persistă și nu se trimite sursei. Importul nu acceptă cookies, user/parolă sursă sau conținut din cont/checkout/admin. „Este public” nu înseamnă automat „am dreptul să-l republic”: atestarea de autorizare + auditul actorului sunt obligatorii.
Starea canonică pentru această bandă este clone_crawl_jobs.options.websiteImport + clone_crawl_pages; nu .symbai-clone/. Coada locală .symbai-clone/ rămâne pentru planul de design și munca agentului după seed.
Uneltele de copiere pe server
Crawl-ul greu rulează pe server (owner-ul poate închide laptopul) — tu doar mapezi din cache și verifici. (Descoperire + crawl + 3 porți-produs mai jos; porțile advisory + SEO sunt în Faza 4.)
list_clone_crawl_pages(jobId, type, status, limit, offset) — coada de lucru: toate URL-urile tipizate (product/category/blog/legal/page) cu status. Sursa adevărului pentru „ce mai am de făcut".
get_cached_page(jobId, url) — conținut + date structurate extrase pentru O pagină (nume, SKU, preț, preț vechi, poze, descriere, breadcrumb, specs PDP, variantCount). De aici mapezi un produs/pagină în Symbai, fără re-descărcare. Pentru paginile NON-produs întoarce și sections[] — inventarul OBIECTIV de secțiuni al paginii-sursă (heading, volum de text textChars, imagini lazy-load-aware, CTA-uri, bgHints culori de fundal inline): numitorul de design al paginii. Dacă sursa are 11 secțiuni și tu ai construit 3, e FAIL măsurabil, nu opinie. Cu el seedezi design-plan.json (vezi mai jos).
clone_parity_diff(jobId, brandId) — POARTA 1 (acoperire produse): compară SETUL de produse-sursă (chei SKU) cu cele importate → întoarce ID-urile care LIPSESC. PASS doar dacă denominatorConfident ȘI nu lipsește nimic.
clone_fidelity_audit(jobId, brandId, sampleSize?) — POARTA 2 (calitate produse, adâncime): eșantion din TOT catalogul, comparat CÂMP-CU-CÂMP cu importul (nume/poze/galerie/descriere/preț/categorie/specs/variante) → fidelityScore + fieldScores + worstSample (ce câmp lipsește, pe ce produs) + flags. fieldScores.gallery prinde importuri de tip „1 poză din 8"; low_gallery_fidelity se repară cu bulk_set_product_images.
clone_coverage_audit(jobId, brandId) — POARTA 3 (tot ce NU e produs): set-diff pe sursă vs importat → coverage + per dimensiune. O migrare reală aduce și astea, nu doar catalogul.
Cum lucrezi cu userul — INCREMENTAL, una câte una (mod IMPLICIT)
Implicit, lucrezi user-driven, NU autonom pe ore. Modul „rulează ore, nu te opri" (Faza 5 + harness.md §Nu-te-opri: /loop, agentul programat, hook-ul Stop) este OPT-IN — îl pornești DOAR după ce userul îți cere explicit „rulează tot / nu te opri / las-o să meargă / închid laptopul". Până atunci toată mașinăria „nu te opri" stă OPRITĂ.
De ce: lecția #1 dintr-o clonare reală — când faci prea mult într-un singur prompt NU verifici destul și scapi greșeli (poze lipsă, link-uri care pleacă de pe clonă, componente nemapate). Verificarea temeinică CERE pași mici. Mai bine durează ore în pași verificați decât „pare gata" la 20%.
Reguli ale cadenței (non-negociabile):
Descompune. Orice lucrare mare (clonarea unui site) o spargi într-o listă numerotată de sarcini mici, fiecare verificabilă singură (ex.: „confirmă numitorul", „mapează ACEASTĂ categorie de ~20 produse", „importă pagina Despre și arat-o", „localizează link-urile din blog"). Ține lista pe disc — catalogul în progress.json, paginile de prezentare în design-plan.json (pe secțiuni) — nu în cap. Userul îți poate cere oricând „arată-mi planul" sau îți poate da el planul: îl scrii pe disc și îl urmezi bucată cu bucată.
O singură sarcină pe tură. Faci EXACT o sarcină mică pe tură. Niciodată nu înlănțui mai multe sarcini în tăcere.
Verifică obiectiv, în aceeași tură. Înainte să mergi mai departe, confirmi sarcina prin CITIREA câmpurilor scrise (re-citești din Symbai ce ai scris) — și, pentru pagini, vizual în browser — nu prin „tool success". „Gata" la o sarcină mică ≠ „pare gata".
Explică în limbaj de business. Spui userului, scurt și pe înțeles, CE ai făcut la sarcina asta și de ce — nu jargon, nu dump de cod.
Propune ÎNTOTDEAUNA următoarea sarcină și oprește-te. Închei fiecare tură cu: (a) rezultatul sarcinii curente + dovada verificării, (b) o singură sarcină următoare concretă, propusă. Apoi te OPREȘTI și aștepți ca userul să zică „continuă / da / yes". Userul conduce ritmul.
Niciodată „gata" fără verificare și niciodată întreg catalogul/site-ul într-o singură tură. „Gata" pe tot rămâne definit de porțile obiective (Regula 1 de mai jos) — porțile rulează doar după ce userul a aprobat parcurgerea.
Chiar și în modul autonom (opt-in), fă checkpoint: după fiecare poartă care trece sau fiecare N loturi, postezi o linie de progres + următoarea sarcină planificată, ca userul să poată interveni.
⚠ Reguli NON-NEGOCIABILE (din ele vine corectitudinea)
„Gata" NU înseamnă „pare copiat". „Gata" = clone_audit_all(...).data.pass === true (porțile dure trec + advisory nu blochează) sau, dacă rulezi manual, TOATE porțile dure pass:true — clone_parity_diff (0 produse lipsă, numitor sigur) ȘI clone_fidelity_audit (câmpurile produselor transferate, inclusiv galerie când sursa are 2+ poze) ȘI clone_coverage_audit (categorii/blog/pagini legale migrate) — PLUS Poarta 4 (fidelitate de design, Faza 4b): paginile de prezentare arată ca originalul, verificat vizual — PLUS audit_shop_health fără error. Niciodată pe baza impresiei tale.
Numitorul mai întâi. Dacă denominatorConfident:false, NU începe să declari progres procentual fals. Obține un al doilea semnal (vezi harness.md §Numitor) sau spune-i EXPLICIT userului „best-effort, denominator nesigur (motiv)" — nu ascunde.
Cheia de identitate = SKU / handle / slug-sursă, NU numele. Setează câmpul sku al fiecărui produs = cheia sursă la import (bulk_create_products(sku=<cheie>)). Altfel bulk_create_products deduplică pe NUME și îmbină tăcut produse distincte → pierdere de date care „trece" la numărătoare.
Niciodată tot catalogul într-o singură trecere. Descompune în loturi mici (≤25 produse / 1 pagină) date la sub-agenți (Task tool) cu context curat; tu (liderul) ții doar coada + tally-ul, nu HTML-ul paginilor.
Coada trăiește pe DISC (.symbai-clone/), nu în context. La fiecare iterație/sesiune nouă, prima acțiune = re-citește coada și reia; nu te baza pe memorie după compactare.
„Buget epuizat" ≠ „complet". Dacă atingi un plafon de timp/cost, starea finală e INCOMPLET cu numărul de ID-uri rămase afișat — niciodată COMPLET.
Idempotent. Re-rularea unui lot trebuie să fie no-op (cheia stabilă + dedup Symbai). Verifică prin CITIRE a câmpurilor, nu prin „tool success".
Paginile de prezentare se copiază pe DESIGN, nu pe text. O pagină (acasă, despre, servicii, abonamente, blog, legale) NU se toarnă într-un singur bloc custom-HTML. Fiecare secțiune-sursă se mapează la o componentă nativă de website-builder (hero, text+imagine, carduri, galerie, testimoniale, FAQ, pricing) ca tema s-o stilizeze. „Arată ca originalul" e o POARTĂ (vezi Poarta 4), nu o impresie. Verificarea finală e vizuală, pagină-cu-pagină, componentă-cu-componentă în browser — exact cum verifică ownerul.
Fluxul (faze)
Faza 0 — Scop & numitor onest
list_brands → brandId (sau creează brand+locație+depozit dacă instanța clientului e goală / cont nou — vezi construieste-website).
Dacă denominatorConfident:false: citește flags. single_independent_count/no_independent_count (ex. Magento/OpenCart fără feed JSON) → al doilea semnal: numără produsele dintr-o pagină de listing („N produse/rezultate") pe câteva categorii și extrapolează, SAU continuă marcat „best-effort" și spune-i userului. counts_disagree/denominator_round_cap → reconciliază înainte de a declara vreodată „gata".
Faza 1 — Pornește crawl-ul pe server (hands-free)
start_site_clone_crawl(url, brandId) → jobId. Rulează în fundal pe server. Spune-i userului: „Am pornit copierea pe server — poți închide laptopul; eu continui și verific."
Poll get_clone_crawl_status(jobId) periodic. Nu aștepta să termine 100% ca să începi maparea — mapează pe măsură ce paginile devin cached.
Faza 2 — Coada durabilă pe disc
Creează .symbai-clone/<host>/ cu manifest.json (numitor + goldProducts), progress.json (header/tally), design-plan.json (design DNA + planul pe pagini/secțiuni — schema în references/harness.md) și flag-ul .pending-clone-<sessionId>. (Crawl-ul e deja persistent pe server; fișierele locale sunt tally-ul tău + poarta hook-urilor „nu te opri".)
6b. Design DNA (înainte de ORICE scriere vizuală): deschide site-ul REAL în browser și extrage paleta COMPUTED (header, hero, benzi de conținut, butoane), fontul (link fonts + computed pe h1/body), formele (radius butoane/carduri). Scrie-le în design-plan.json → designDna, fiecare valoare CU dovada ei („navbar computed background", „culoarea dominantă din logo"). De aici — și NUMAI de aici — vin culorile/fonturile pe care le scrii în configuri (Regula 10). clone_branding_audit îți dă semnalele de bază (logo/culoare temă); browserul le rafinează pe roluri semantice.
Faza 3 — Mapează în loturi, cu sub-agenți
Buclă: list_clone_crawl_pages(jobId, type:"product", status:"cached", limit, offset) → ia un lot de ~25. Dă-l unui sub-agent (Task) cu instrucțiune strictă: pentru fiecare URL → get_cached_page → bulk_create_products(sku=cheia sursă, name, description, vat:21, ...) + set_product_image/bulk_set_product_images + add_menu_item(productBrand, ...); întoarce DOAR {lot, produseScrise, pozeScrise, eșecuri[]}. Apoi categorii (ierarhie din breadcrumb → bulk_reparent_menu_categories + set_products_menu_category), blog (bulk_create_blog_posts), legale (set_website_legal_page), footer/branding.
⚠ Parcurge TOATE tipurile, nu doar type:"product"/type:"page". Coada are product/category/blog/legal/page — fiecare cu importatorul lui. Dacă filtrezi importul de pagini pe type:"page", pierzi tăcut paginile cu type:"legal"/type:"blog" (într-o clonare reală au lipsit mai multe pagini exact așa). Iterează pe toate tipurile relevante.
După fiecare lot, actualizează progress.json. Liderul citește doar header-ul + cere următorul lot — nu încarcă tot catalogul în context.
Faza 4 — Verifică (cele 3 porți obiective, în ordine)
Poarta 1 — acoperire produse: clone_parity_diff(jobId, brandId). Dacă pass:false: pentru fiecare ID din missingSample → get_cached_page → re-importă. Re-rulează până pass:true.
9b. Poarta 2 — calitate produse: clone_fidelity_audit(jobId, brandId). Pentru fiecare intrare din worstSample (produs + câmpuri lipsă) → get_cached_page(jobId, url) → completează câmpul: poze/galerie (set_product_image/bulk_set_product_images, prima poză = copertă), descriere/preț-vechi/specs (update_menu_item/add_menu_item), variante (set_product_variants), categorie (set_products_menu_category). Re-rulează până pass:true. Citește flags: low_gallery_fidelity → produsul are prea puține poze față de sursă; unreadable_source_pages_* → re-citește sursa; price_currency_mismatch_suspected → verifică valuta; unaudited_fields_* → câmp absent în sursă (nimic de făcut).
9c. Poarta 3 — non-produs: clone_coverage_audit(jobId, brandId). Pentru fiecare missingSample per dimensiune → importă din get_cached_page: categorii (create_menu_category/bulk_reparent_menu_categories), blog (bulk_create_blog_posts), pagini legale (set_website_legal_page). Re-rulează până fiecare dimensiune ≥95%.
9c-arbore. Arbore categorii (advisory): clone_category_tree_audit(jobId, brandId). pass poate fi null (sursă fără breadcrumb-uri = neauditabil, OK). Dacă pass:false sau flatteningDetected:true: pentru fiecare missingEdgesSample (parent>child) → create_menu_category (categoriile lipsă) + bulk_reparent_menu_categories (leagă copil→părinte, ca arborele să nu fie plat). Re-rulează până pass ∈ {true, null}.
9c-branding. Branding (advisory): clone_branding_audit(jobId, brandId). poate fi (sursă fără semnale vizuale). Dacă : din → + (logos/colors/socialMedia); contactul (telefon/email/adresă din ) → . Re-rulează până ∈ {, }.
9d. → repară toate , re-rulează până curat.
9e. . Rulează la final sau când vrei status executiv. înseamnă că porțile dure trec și advisory nu blochează; înseamnă că nu poți declara complet, chiar dacă restul arată bine.
9f. . După ce porțile trec, scrie 301-uri din URL-urile VECHI (produs/categorie) spre cele noi Symbai, ca firma să NU piardă pozițiile Google când mută domeniul. Rulează ÎNTÂI dry-run (fără ) ca să vezi //; dacă e mare, mai întâi închide golurile (parity/coverage), apoi . (Esențial la o migrare reală cu trafic.)
Faza 4b — Poarta 4: fidelitate de DESIGN (paginile de prezentare)
Catalogul poate fi 100% și site-ul tot să arate „groaznic" dacă paginile sunt text simplu fără designul sursei.
Protocolul plan → loop (obligatoriu, Regula 11):
0. Inventariază ÎNTÂI, construiește DUPĂ. Pentru fiecare pagină non-produs din coadă (list_clone_crawl_pages type page/legal/blog + home + paginile de categorie-cheie): get_cached_page(jobId, url) → citește sections[] (numitorul de secțiuni) → scrie pagina în design-plan.json cu TOATE secțiunile ei (sourceSectionCount, per secțiune: heading/imagini/CTA/bgHints din tool + mappedType propus + status:"todo"). O pagină fără inventar scris pe disc NU se construiește. Arată-i userului planul ca listă numerotată („pagina X: N secțiuni") când îl termini.
Loop — o bucată pe iterație: ia URMĂTORUL item nebifat din design-plan (o pagină mică întreagă SAU o singură secțiune pe pagini mari). Mapează componentă-cu-componentă (cu construieste-website): fiecare secțiune-sursă → componentă nativă echivalentă, cu fundalul/banda colorată (din bgHints + designDna), pozele, butoanele CTA (localizate) și animațiile pe care le are originalul. NU dump custom-HTML. Verifică bucata (pașii 2-3), bifeaz-o cu dovadă (status:"verified" + proof), actualizează design-plan.json, apoi propune următoarea bucată. NU înlănțui mai multe bucăți neverificate.
Agent de verificare structural (rulează după fiecare import): începe cu get_website_page(brandId, pageSlug) ca read-back live, apoi fă diff împotriva sections[] din get_cached_page (numitorul obiectiv, nu memoria ta): fiecare secțiune-sursă are un echivalent construit? → semnalează secțiuni lipsă, poze lipsă (compară cu images[] per secțiune), componente vizuale pierdute, text comprimat agresiv (textChars mare în sursă vs. un rând la tine), link-uri ne-localizate (doar href/src, nu URL-uri ca text afișat). Listează paginile de verificat vizual, worst-first. Nu număra ca „lipsă" tipurile care fuzionează firesc (titluri/rich-text → text-block) sau cele ne-vizuale (formulare) — altfel ai zgomot.
Pas vizual în browser (Chrome): deschide URL-ul REAL și echivalentul local unul lângă altul și compară componentă-cu-componentă (poze, benzi, box offset, fonturi, CTA, animație reveal). Notează diferențele → repară maparea → re-importă → re-verifică. Pe pagini cu multe imagini screenshot-ul poate da timeout: verifică structura cu interogări DOM (componente prezente + datele lor), nu doar poze.
Verifică EXPLICIT că fiecare rută randează conținutul EI (acasă ≠ meniu; /blog = listarea blogului; /<pagină> = pagina ei, nu homepage-ul). Un fallback tăcut la home/meniu (pagină neimportată) = pagină LIPSĂ, nu PASS. Într-un caz real, homepage-ul arăta meniul și /blog arăta tot meniul exact din cauza asta.
POARTĂ: zero poze-lipsă, zero benzi colorate pierdute, zero recenzii-imagine aruncate, zero animații reveal lipsă, zero componente vizuale pierdute, zero link-uri navigaționale ne-localizate, fiecare rută randează conținutul ei (zero fallback la home/meniu), zero pagini stale (re-importate după orice fix de mapare — Regula 9), (zero / rămase — Regula 11) și (fiecare culoare/font scris în configuri e trasabil la ; o valoare „de la site-ul trecut" = FAIL — Regula 10). Abia atunci pagina e „ca originalul".
Capcane de mapare → Verificare (fiecare a stricat o clonă reală). Bifează-le UNA CÂTE UNA pe fiecare componentă — nu „dintr-o privire":
Poză în câmp neevident.image e adesea gol; poza reală e în imageMask, picture (ImageCards), heroSectionSliderItems[] (hero) sau backgroundImage (scroll-list). → Probează TOATE câmpurile de imagine înainte să declari „fără poză".
Cutia decorativă din spate = o IMAGINE (imageBackgroundMask), nu o culoare. → mapeaz-o ca background-image.
Banda colorată de secțiune = câmp real al componentei (backgroundColor / box+boxColor), nu alb implicit. → setează sectionBg + sectionTextColor (ambele).
text-image bogat, nu custom inutil. Pentru secțiuni split folosește componenta nativă cu html, eyebrow, eyebrowColor, titleColor, ctaColor, backgroundImageUrl, backgroundOverlay, imageBoxColor/imageBoxImage, imageMask, imageShadow, decor. Abia dacă schema nu exprimă designul treci la custom-html.
Culorile sunt SEMANTICE — nu vopsi secțiuni întregi cu o culoare-accent. Calibrează pe culorile COMPUTED ale site-ului real (inspectează în Chrome): navy = eroi, light-blue = benzi de conținut, roz/galben = ACCENTE (boxuri, benzi de recenzii), niciodată erou full-bleed. Ex.: DarkTextBoxSection.boxColor e boxul din spatele IMAGINII, nu fundalul secțiunii (secțiunea = navy când textul e alb). Un text+imagine fără culoare → secțiune light-blue implicit, FĂRĂ box inventat.
Blog = Markdown. Renderul de blog NU afișează HTML brut. → convertește HTML→Markdown; restaurează entitățile dublu-escapate (&nbsp; → ).
NU trec prin localizatorul de href/src. → rescrie-le MANUAL la slug-ul Symbai (cazul , paginile legale).
Update 2026-06-24 - mapping-uri native pentru fidelitate vizuala
Inainte sa marchezi o sectiune ca necesitand custom-html, verifica aceste optiuni live din website builder:
Hero corporate cu panou diagonal si poza: hero-slider cu heroLayout:"diagonal-split", backgroundColor, diagonalAccentColor, panelWidth, dots/arrows/autoplay cand sursa are slider.
Hero index editorial: index-hero cu items:[{label,image,url}], height, align, overlayColor, activeColor, ctaText, ctaUrl pentru liste verticale de locatii/destinatii/colectii care schimba imaginea pe hover/focus (hotel groups / The Standard). Nu il inlocui cu grila sau custom HTML.
Titlu bicolor / rand accentuat: slides[].titleAccent; pastreaza slides[].title ca primul rand. Pentru litere cu contur foloseste titleStroke + titleStrokeWidth.
Beneficii in coloane minimaliste: feature-cards cu style:"divided", cards[].description si cards[].linkText; pentru titlu de sectiune aliniat stanga/dreapta sau pe doua randuri foloseste titleAlign si \n in title.
Carduri filtrabile: tabbed-cards cu tabs[], cards[].tab si showAllTab pentru servicii sau portofolii filtrate. Pentru pagina reala de locatii/restaurante/hoteluri cu harta si directii, foloseste store-locator.
Localizator cu harta: store-locator cu locations:[{name,address,city,region,hours,phone,mapQuery,directionsUrl}], regions, allRegionLabel, mapHeight pentru pagini "Find us" / "Restaurants" / "Locations"; filtrele pe regiune sunt interactive si recentreaza harta.
Lista editoriala + imagine: split-list pentru servicii/oferte/valori/pasi cu titluri subliniate, descrieri si linkuri langa fotografie; pastreaza imagePosition, titleUnderline, dividers si culorile originale.
Carusel editorial: content-carousel pentru destinatii, experiente, pachete sau povesti afisate cate una cu sageti/dots; continutul e inline, nu POS live.
Pasi / cum functioneaza: pentru sectiuni "how it works", abonamente, flux comanda/livrare sau experienta in 3-5 pasi; pastreaza , , si culorile.
Acestea trebuie bifate in Poarta 4 de design: screenshot desktop + mobil pentru hero diagonal, text-image diagonal si reveal la scroll, read-back pentru footer/navbar/tema si comparatie vizuala cu originalul.
Faza 5 — Nu te opri până nu e gata (mod AUTONOM, OPT-IN)
Aceasta e modul AUTONOM — pornește-l DOAR după ce userul cere explicit „rulează tot / nu te opri / las-o să meargă". În modul IMPLICIT (vezi „Cum lucrezi cu userul"), după FIECARE sarcină mică verificată te oprești și propui următoarea. În modul autonom, fă checkpoint: după fiecare poartă care trece sau fiecare N loturi, postează o linie de progres + următoarea sarcină planificată, ca userul să poată interveni.
Buclă până: coada goală (0 pending în list_clone_crawl_pages) ȘI clone_audit_all(...).data.pass === true (sau cele 3 porți produs pass:true — clone_parity_diff + clone_fidelity_audit + clone_coverage_audit — + advisory rezolvat/N-A) ȘI Poarta 4 design (Faza 4b) trecută vizual, cu design-plan.json complet verified ȘI audit_shop_health fără error. Fiecare trezire a buclei procesează O bucată din plan (Regula 11) — nu „cât mai mult".
Pentru rulare pe ore, nesupravegheat (owner-ul a plecat): instalează un agent programat care reia skill-ul cât timp mai există pending (vezi references/harness.md §Nu-te-opri + skill-ul schedule). Hook-ul Stop (dacă e instalat) e podeaua dură. /loop e bucla din sesiune.
Re-citește progress.json la fiecare reluare; revendică rândurile in_progress rămase blocate înapoi la pending.
Raport onest (la final)
Nu spune „gata" decât la PASS real pe TOATE trei porțile. Raportează: produse importate / numitor + fidelityScore (calitate câmpuri, din Poarta 2) + acoperirea non-produs (categorii/blog/pagini legale, din Poarta 3), paginile de design verificate / total din design-plan.json (cu secțiuni sursă acoperite), poze %, ID-uri pe dead-letter (cu motiv: 404/login/fără preț), și ce a rămas NESIGUR. Dacă numitorul a fost nesigur, spune-o. Rezumă userului 3-4 lucruri cheie făcute, în limbaj de business.
Capcane (vezi și harness.md)
Site fără sitemap (unele OpenCart) → discover_site_inventory întoarce 0 cu no_independent_count. NU înseamnă „site gol" — înseamnă „nu pot stabili scopul din sitemap"; pornește crawl-ul (folosește link-crawl/categorii) și marchează numitorul nesigur.
Magento: sitemap-ul de produse supranumără (include produse scoase din stoc). Numitorul din sitemap = plafon superior, marcat nesigur — reconciliază cu listing-urile.
Poze: trec prin URL sursă la set_product_image (Symbai le ia); dacă CDN-ul sursă cade, re-rulează din cache.
TVA România = 21 (nu 19). Idempotency pe SKU, nu pe nume.
categorii / blog / pagini legale
missingSample
clone_category_tree_audit(jobId, brandId) — advisory (Faza 4, 9c-arbore): verifică arborele de categorii (părinte→copil) vs aplatizare; pass poate fi null dacă sursa n-are breadcrumb-uri.
clone_branding_audit(jobId, brandId) — advisory (Faza 4, 9c-branding): logo / culori / nume / social / contact din sursă vs brandul Symbai; pass poate fi null fără semnale vizuale.
clone_audit_all(jobId, brandId, sampleSize?) — verdict complet, read-only, într-un apel: rulează parity + fidelity + coverage + tree + branding și întoarce pass, hardPass, erroredGates, sumar per-poartă și remedieri.
clone_redirect_map(jobId, brandId, apply?) — continuitate SEO (Faza 4, 9f): dry-run, apoi apply:true scrie 301-uri din URL-urile vechi produs/categorie spre URL-urile Symbai. Rulează ÎNTÂI dry-run, separat după PASS.
Pentru paginile de prezentare (non-produs): conținutul se scrie cu uneltele din construieste-website (set_website_theme → update_website_navigation → set_website_page_content/set_website_pages/set_website_legal_page) și se verifică prin get_website_page înainte de browser — vezi Faza 4b. Foloseste set_website_pages cand imporți multe pagini odata.
Orice corecție de mapare/renderer invalidează output-ul vechi. După ce repari un mapper sau un renderer (sau adaugi un tip de componentă), RE-importă paginile afectate ÎNAINTE de re-verificare. Un fix ne-reimportat = output stale care trece fals la verificare. Verifici versiunea NOUĂ, nu cea veche.
⚠ ANTI-CONTAMINARE: designul vine DOAR din site-ul pe care îl copiezi ACUM. La fiecare clonare NOUĂ pornești cu ochi proaspeți: site-ul clonat DATA TRECUTĂ (paleta lui, fonturile lui, layout-urile lui, exemplele lui) NU e referință — nici din memorie, nici din sesiuni vechi, nici din exemplele catalogului. Orice culoare / font / valoare vizuală pe care o scrii într-un config trebuie să fie TRASABILĂ la o dovadă din site-ul CURENT (culoare computed inspectată în browser, culoarea din logo, font din <link> fonts) — dovada o ții în designDna din design-plan.json. Valoare fără dovadă = contaminare → n-o scrii. Exemplele din catalogul de componente sunt STRUCTURALE (arată câmpurile), nu palete de copiat. Simptomul clasic al încălcării: „site-ul nou seamănă cu site-ul copiat săptămâna trecută, nu cu sursa lui".
Fidelitatea pe pagini se ține într-un PLAN durabil pe disc, lucrat în BUCLĂ — o bucată pe iterație. Nu construiești nicio pagină de prezentare înainte ca inventarul ei de secțiuni să fie scris în design-plan.json (seedat din get_cached_page(...).sections). Apoi loop: iei O pagină (sau O secțiune, pe pagini mari) → o construiești → o verifici (read-back + vizual) → o bifezi cu dovadă → treci la următoarea. Chiar dacă durează mai mult, fiecare bucată e făcută CORECT și nimic nu e sărit — planul de pe disc arată mereu, obiectiv, ce a rămas. „Am terminat designul" = toate paginile din design-plan au status:"verified", nu o impresie.
SEO — redirecturi 301: clone_redirect_map(jobId, brandId, apply:true)
apply
unmatched
noSlug
chainsSkipped
unmatched
apply:true
toate paginile din design-plan.json cu status:"verified"
todo
built
zero contaminare
designDna
Link-uri în corpul rich-text / descriptionHtml / custom-html
RichTextHtml
Recenzii doar-imagine.reviewItems[] fără text — recenzia e un screenshot în authorPicture. → randează galerie; NU lăsa un filtru pe text să arunce secțiunea.
Liste „scroll list" (ScrollListSection): itemele reale sunt în boxes[].boxCards[] (fiecare {image,title,text}), NU în boxes[].boxTitle; poza de secțiune e în backgroundImage (nu image). → intro text+imagine din backgroundImage + feature-cards din boxCards.
ProductsList ca secțiune de pagină (meniu inline): products.data e adesea gol (încărcat client-side) → afișează imaginea de menu. Mapeaz-o explicit, altfel pierzi tăcut secțiunea.
Componente care fuzionează / ne-vizuale (titluri + rich-text → text-block; formulare) — normal să scadă numărul la import; NU le număra ca „lipsă" (altfel verificatorul dă fals-pozitiv).
Navbar-ul = meniul REAL al sursei, nu lista auto de pagini. Inspectează în browser meniul site-ului real (itemii de top + dropdown-urile lor + href-uri) și reconstruiește-l 1:1 cu update_website_navigation items[] (suport children[] pentru dropdown). Default-ul (o intrare per pagină: Acasă/Atracții/Restaurant/...) NU corespunde. Și ascunde butonul CTA din dreapta dacă originalul n-are (navbarSettings:{ctaButton:{visible:false}}). Daca originalul are meniu lateral stanga, foloseste navbarSettings:{style:"sidebar-left", sidebarBg, sidebarTextColor, socialLinks:[...]}.
NU activa „extra"-uri de componentă pe care sursa NU le are. Componentele Symbai au opțiuni implicite decorative (sidebar de blog cu newsletter + „Recente", badge „Popular"/„Recomandat", toggle de facturare lunar/anual, rating badge, „featured hero"). Activează-le DOAR dacă site-ul real le are. Ex.: dacă blogul sursă NU are sidebar → blog-listing.showSidebar=false (altfel apare un „Abonează-mă" care nu există în original). Compară layout-ul real (câte coloane, cu/fără sidebar, cu/fără badge) și oglindește-l — un element în plus strică fidelitatea la fel ca unul lipsă.
process-steps
layout
numberStyle
connectors
Ticker/marquee: marquee cu items[], speed, separator, direction, textCase, culori pentru benzi derulante cu slogane repetate; nu folosi GIF/video/custom HTML. Pentru branduri lowercase seteaza textCase:"lower".
Banda App Store / Google Play: app-download cu appStoreUrl, googlePlayUrl sau stores[], optional image cu telefon, pentru sectiuni de tip order-ahead, loialitate, livrare sau "download our app"; nu o recrea ca custom-html.
Meniu restaurant static: menu-list cu layout:"grid"|"list", items[]/categories[], pret, meta/kcal, badge-uri, tag-uri dietetice, spice, filters:true, filterTags si culori. Foloseste-l pentru pagini de marketing/clone, inclusiv filtre Vegan/Vegetarian/Gluten-free; daca userul cere meniu POS live, nu-l folosi ca substitut al catalogului.
Fundal light mode: set_website_theme(backgroundColor, textColor?) cand originalul are fundal cream/warm/branded; verifica desktop + mobil ca nu a ramas alb implicit.
Footer complet de magazin: set_website_footer cu description, paymentMethods, showAnpc si socialLinks custom sigure (ex. tripadvisor, whatsapp, booking), pe langa contact/columns.
Navbar/chrome: update_website_navigation aplica navbarSettings direct, inclusiv sidebar-left, navbarBg pentru bare solide pe fundal cream/branded, logoRotate:180 pentru wordmark rasturnat, logoBg pentru cutie colorata in spatele logoText si ctaButton:{style:"outline"} / ctaButton:{style:"outline",color:"#c9a45c"} pentru CTA contur cu culoare default sau custom. Daca navbarBg e inchis la culoare, rendererul comuta automat textul/logo/iconitele pe light; verifica prin get_website_page + screenshot dupa scriere.
CTA solid custom: pentru buton navbar plin cu fundal/text de brand, foloseste ctaButton:{style:"solid",bgColor:"#173f35",color:"#ccff00"} si verifica read-back in navbar.
Navbar transparent / logo contextual: navbarSettings.transparent:true pluteste peste hero doar daca pagina incepe cu hero, hero-slider, image-hero sau index-hero; pe pagini light devine solid si poate folosi logoUrlDark. Pentru selector valuta seteaza showCurrency:true + currencies. Verifica vizual home + cel putin o subpagina.
Reveal-on-scroll global: daca originalul are sectiuni care apar la scroll, seteaza set_website_theme(scrollReveal:true). Verifica in browser ca efectul se vede pe sectiuni editoriale si ca elementele sticky/fixed raman functionale; rendererul exclude hero/navbar/footer/marquee si respecta prefers-reduced-motion.
Text+imagine cu muchie diagonala: pentru sectiuni split cu fotografie taiata oblic spre text, foloseste text-image.imageMask:"diagonal"; masca se intoarce automat cu pozitia imaginii, deci nu marca sectiunea ca fiind custom doar pentru aceasta forma.