/diego/ecxm-ops EscríbemeWrite to meEscriu-me
AI Engineer · operaciones · e-commerce COD ColombiaAI Engineer · operations · COD e-commerce, ColombiaAI Engineer · operacions · e-commerce COD Colòmbia

Construí el sistema operativo de un negocio entero, y el gate que le impide mentir con dinero.

I built the operating system of an entire business, and the gate that stops it lying about money.

Vaig construir el sistema operatiu d'un negoci sencer, i el gate que li impedeix mentir amb diners.

ECXM OPS cubre la cadena completa de un negocio de dropshipping COD, de espiar a la competencia a cerrar el mes, en un solo dashboard y una CLI de 35 comandos. El modo de fallo no es que Streamlit pete: es que el pivot afirme con total fluidez una utilidad neta falsa. Un decimal mal atribuido es el sueldo de otra persona.

ECXM OPS covers the full chain of a COD dropshipping business, from spying on competitors to closing the month, in one dashboard and a 35-command CLI. The failure mode isn't Streamlit crashing: it's the pivot fluently asserting a false net profit. One misattributed decimal is somebody else's pay.

ECXM OPS cobreix la cadena completa d'un negoci de dropshipping COD, d'espiar la competència a tancar el mes, en un sol dashboard i una CLI de 35 comandes. El mode de fallada no és que Streamlit peti: és que el pivot afirmi amb tota fluïdesa una utilitat neta falsa. Un decimal mal atribuït és el sou d'una altra persona.

En uso diario en mi propio negocio desde mayo de 2026, con 6.286 anuncios de la competencia indexados. Construido en solitario, con IA.In daily use in my own business since May 2026, with 6,286 competitor ads indexed. Built solo, with AI.En ús diari al meu propi negoci des del maig del 2026, amb 6.286 anuncis de la competència indexats. Construït en solitari, amb IA.

etapas encadenadas · espiar → analizar → clonar → crear → vender → cerrar → decidirchained stages · spy → analyse → clone → create → sell → close → decideetapes encadenades · espiar → analitzar → clonar → crear → vendre → tancar → decidir
facturas OCR en 4 divisasOCR invoices in 4 currenciesfactures OCR en 4 divises
$
coste LLM del clonador de landings · era ~$0,05 por landing con VisionLLM cost of the landing cloner · it used to be ~$0.05 per landing with Visioncost LLM del clonador de landings · era ~$0,05 per landing amb Vision
/3
gates golden en verde por igualdad exacta · uno de ellos decide una liquidacióngolden gates green on exact equality · one of them decides a payoutgates golden en verd per igualtat exacta · un d'ells decideix una liquidació
RecorridoWalkthroughRecorregut

Un producto entra por un extremo y sale una liquidación por el otro

A product goes in one end and a payout comes out the other

Un producte entra per un extrem i en surt una liquidació per l'altre

No son siete scripts sueltos: es una sola cadena donde la salida de cada etapa es la entrada de la siguiente, y donde el estado vive en archivos que las demás etapas saben leer. Pulsa cualquier estación para ver qué hace, qué cuesta y con qué se sincroniza.

These aren't seven loose scripts: it's a single chain where each stage's output is the next one's input, and where state lives in files the other stages know how to read. Click any station to see what it does, what it costs and what it syncs with.

No són set scripts solts: és una sola cadena on la sortida de cada etapa és l'entrada de la següent, i on l'estat viu en fitxers que les altres etapes saben llegir. Prem qualsevol estació per veure què fa, què costa i amb què se sincronitza.

vista previa · corte heropreview · hero cutvista prèvia · tall hero

Guion: escaneo de la Ads Library → producto al LAB (precios + copy + títulos) → réplica de la landing en $0 → creativos → control diario → cierre de mes → la tabla que dice qué producto es winner.Script: Ads Library scan → product into the LAB (pricing + copy + titles) → landing replica at $0 → creatives → daily control → month close → the table that says which product is a winner.Guió: escaneig de l'Ads Library → producte al LAB (preus + copy + títols) → rèplica de la landing en $0 → creatius → control diari → tancament de mes → la taula que diu quin producte és winner.

Estas 7 etapas del ciclo del producto viven en 6 pestañas del dashboard (cerrar y vender comparten FINANZAS). Hay 3 más de soporte (FEEDBACK, ACADEMIA y ROADMAP, que renderiza el mapa de arquitectura del propio dashboard) 9 en total.These 7 product-cycle stages live in 6 dashboard tabs (sell and close share FINANCE). There are 3 more support tabs (FEEDBACK, ACADEMIA and ROADMAP, which renders the dashboard's own architecture map) 9 in total.Aquestes 7 etapes del cicle del producte viuen en 6 pestanyes del dashboard (tancar i vendre comparteixen FINANCES). N'hi ha 3 més de suport (FEEDBACK, ACADÈMIA i ROADMAP, que renderitza el mapa d'arquitectura del mateix dashboard) 9 en total.

Flagship · la superficie irreversibleFlagship · the irreversible surfaceFlagship · la superfície irreversible

La única cifra del sistema que se convierte en el pago de una persona

The one figure in the system that turns into somebody's pay

L'única xifra del sistema que es converteix en el pagament d'una persona

El contrato del equipo tiene una cláusula corta: un producto es winner si cierra el mes con utilidad neta positiva, y entonces el reparto pasa de 50/50 a 40/60 a favor del colaborador. Toda la maquinaria de abajo existe para producir ese número. El dashboard está hecho para que yo confíe y cierre rápido: esa confianza es exactamente lo que convierte un error de atribución en dinero mal repartido.

The team contract has one short clause: a product is a winner if it closes the month with positive net profit, and then the split moves from 50/50 to 40/60 in the collaborator's favour. All the machinery below exists to produce that number. The dashboard is built so I trust it and close fast: that trust is exactly what turns an attribution error into money paid out wrong.

El contracte de l'equip té una clàusula curta: un producte és winner si tanca el mes amb utilitat neta positiva, i llavors el repartiment passa de 50/50 a 40/60 a favor del col·laborador. Tota la maquinària de sota existeix per produir aquell número. El dashboard està fet perquè jo m'hi confiï i tanqui de pressa: aquesta confiança és exactament el que converteix un error d'atribució en diners mal repartits.

WALLET DropiDropi WALLETWALLET Dropi fletes reales por pedidoreal shipping cost per orderports reals per comanda FACTURAS · OCRINVOICES · OCRFACTURES · OCR 136 PDFs · 4 divisas · caja real136 PDFs · 4 currencies · real cash136 PDFs · 4 divises · caixa real SERVICIOS + ADMINSERVICES + ADMINSERVEIS + ADMIN repartidos ∝ ventas entregadasallocated ∝ delivered salesrepartits ∝ vendes lliurades PEDIDOS · DropiORDERS · DropiCOMANDES · Dropi export del mesmonth exportexport del mes LIMPIO solo los 4 estatus finalesonly the 4 final statusesnomés els 4 estats finals UTILIDAD NETANET PROFITUTILITAT NETA ventas ENT − flete − costo − facturasDELIVERED sales − shipping − cost − invoicesvendes LLIU − port − cost − factures pivot.utilidad_mes() /eval-finanzas igualdad exacta exact equalityigualtat exacta ¿neta > 0?net > 0?neta > 0? cláusula 4.1clause 4.1clàusula 4.1 WINNER · 40 / 60 60 % para el colaborador60 % to the collaborator60 % per al col·laborador NORMAL · 50 / 50STANDARD · 50 / 50NORMAL · 50 / 50 reparto por defectodefault splitrepartiment per defecte

Pellizca para acercar y leer el detalle ↔Pinch to zoom in and read the detail ↔Pessiga per apropar i llegir el detall ↔

La convención de nombres de campaña en Meta ([NOMBRE]_[PRODUCTO]_[FECHA]) no es cosmética: es lo que permite que el gasto publicitario baje hasta el producto correcto. Si una campaña no la respeta, el sistema lo marca, sin ella la atribución falla y la liquidación se reparte mal.

The Meta campaign naming convention ([NAME]_[PRODUCT]_[DATE]) isn't cosmetic: it's what lets ad spend flow down to the right product. If a campaign breaks it, the system flags it, without it attribution fails and the payout is split wrong.

La convenció de noms de campanya a Meta ([NOM]_[PRODUCTE]_[DATA]) no és cosmètica: és el que permet que la despesa publicitària baixi fins al producte correcte. Si una campanya no la respecta, el sistema ho marca, sense ella l'atribució falla i la liquidació es reparteix malament.

FuenteSourceFont Qué esWhat it isQuè és Regla duraHard ruleRegla dura UsoUseÚs
LIMPIO ventas, estatus y flete del export de Dropisales, status and shipping from the Dropi exportvendes, estats i port de l'export de Dropi solo los 4 estatus finales cuentan para el mes; un pedido en tránsito no tiene resultado todavíaonly the 4 final statuses count for the month; an in-transit order has no outcome yetnomés els 4 estats finals compten per al mes; una comanda en trànsit encara no té resultat basebasebase
FACTURA (OCR) costes, servicios y publicidad leídos de los PDFscosts, services and ad spend read from the PDFscostos, serveis i publicitat llegits dels PDFs es lo que se pagó de verdad; un cobro con estado «Error» no cuentait's what was actually charged; a payment in "Error" state doesn't countés el que es va pagar de veritat; un cobrament amb estat «Error» no compta caja · liquidacióncash · payoutcaixa · liquidació
CSV Ads impresiones, visitas y compras de Metaimpressions, visits and purchases from Metaimpressions, visites i compres de Meta nunca reemplaza a la factura como coste real: no trae ni desglose por campaña ni estado del cobronever replaces the invoice as real cost: it carries neither per-campaign breakdown nor payment statemai substitueix la factura com a cost real: no porta ni desglossament per campanya ni estat del cobrament rendimiento · CPAperformance · CPArendiment · CPA
PRORRATEOALLOCATIONPRORRATEIG servicios repartidos entre productosservices split across productsserveis repartits entre productes es una estimación y se etiqueta como tal; jamás se presenta como coste directo del productoit's an estimate and is labelled as one; never presented as a direct product costés una estimació i s'etiqueta com a tal; mai es presenta com a cost directe del producte estimadoestimatedestimat
# la garantía no la da el prompt — la fuerza un `return None` # ecxm/finanzas/facturas.py :: _convertir_cop tasa = _TASAS_COP.get(divisa_norm, None) if tasa is None: # divisa desconocida: NO inventar tasa 1.0 print(f"AVISO: divisa '{divisa}' desconocida") return None # el dashboard muestra " — " return round(imp * tasa, 2) # antes devolvía el importe SIN convertir: # una factura de 29,75 USD entraba como 29,75 COP # → coste subestimado ~4.200× → un producto # perdedor podía aparecer como winner
# the guarantee isn't the prompt: a `return None` forces it # ecxm/finanzas/facturas.py :: _convertir_cop rate = _TASAS_COP.get(currency_norm, None) if rate is None: # unknown currency: do NOT invent a 1.0 rate print(f"WARNING: currency '{currency}' unknown") return None # the dashboard shows ", " return round(amount * rate, 2) # it used to return the amount UNCONVERTED: # a 29.75 USD invoice landed as 29.75 COP # → cost understated ~4,200× → a losing # product could show up as a winner
# la garantia no la dona el prompt — la força un `return None` # ecxm/finanzas/facturas.py :: _convertir_cop tasa = _TASAS_COP.get(divisa_norm, None) if tasa is None: # divisa desconeguda: NO inventar taxa 1.0 print(f"AVISO: divisa '{divisa}' desconocida") return None # el dashboard mostra " — " return round(imp * tasa, 2) # abans tornava l'import SENSE convertir: # una factura de 29,75 USD entrava com a 29,75 COP # → cost subestimat ~4.200× → un producte # perdedor podia aparèixer com a winner

Abstenerse cuesta 5 segundos; una cifra falsa cuesta una liquidación. Ante un dato incompleto (divisa desconocida, factura sin desglose, mes sin cerrar) el sistema devuelve None y avisa en rojo. Nunca un número plausible sin fuente.

Ese bug era real y estaba vivo: la conversión silenciosa a tasa 1.0 hacía pasar una factura en dólares por pesos colombianos. No lo cazó ningún test verde: lo cazó preguntarle al código de dónde sale este número.

Por eso cada dato lleva su procedencia y las fuentes no se sustituyen entre sí. Mezclar la factura (lo que pagué) con el CSV de Meta (cómo rindió) fue un bug de verdad, no una discusión teórica. Hoy es una regla escrita.

Abstaining costs 5 seconds; a false figure costs a payout. Faced with incomplete data (unknown currency, invoice with no breakdown, month not closed) the system returns None and warns in red. Never a plausible number with no source.

That bug was real and live: the silent 1.0-rate conversion passed a dollar invoice off as Colombian pesos. No green test caught it: what caught it was asking the code where does this number come from.

That's why every value carries its provenance and the sources never substitute for one another. Mixing the invoice (what I paid) with the Meta CSV (how it performed) was a genuine bug, not a theoretical debate. Today it's a written rule.

Abstenir-se costa 5 segons; una xifra falsa costa una liquidació. Davant d'una dada incompleta (divisa desconeguda, factura sense desglossament, mes sense tancar) el sistema torna None i avisa en vermell. Mai un número plausible sense font.

Aquell bug era real i estava viu: la conversió silenciosa a taxa 1.0 feia passar una factura en dòlars per pesos colombians. No el va caçar cap test verd: el va caçar preguntar al codi d'on surt aquest número.

Per això cada dada porta la seva procedència i les fonts no se substitueixen entre si. Barrejar la factura (el que vaig pagar) amb el CSV de Meta (com va rendir) va ser un bug de veritat, no una discussió teòrica. Avui és una regla escrita.

/eval-finanzas check-all
$ python tests/golden_finanzas/eval_finanzas.py check-all

[check] ENERO 2026 — VEREDICTO: PASA (5 productos, igualdad exacta)
[check] MARZO 2026 — VEREDICTO: PASA (4 productos, igualdad exacta)
[check] ABRIL 2026 — VEREDICTO: PASA (3 productos, igualdad exacta)

# el gate corre las FUNCIONES REALES del cierre — pivot.calcular_neta_mes()
# y pivot.utilidad_mes() — contra tres meses cerrados y verificados a mano.
# Sin reimplementar la lógica: si el golden y producción divergen, es un bug
# del golden, no del negocio.
#
# Igualdad EXACTA, no ±tolerancia: el OCR queda fuera de este camino, así que
# dos corridas sobre los mismos inputs dan el mismo número al peso. Una
# tolerancia del 0,5 % enmascararía una regresión real.
#
# Si BLOQUEA, el cambio no se cierra. No es un aviso: es un no.
$ python tests/golden_finanzas/eval_finanzas.py check-all

[check] JANUARY 2026 — VERDICT: PASS (5 products, exact equality)
[check] MARCH   2026 — VERDICT: PASS (4 products, exact equality)
[check] APRIL   2026 — VERDICT: PASS (3 products, exact equality)

# the gate runs the REAL closing functions — pivot.calcular_neta_mes() and
# pivot.utilidad_mes() — against three closed, hand-verified months.
# No reimplemented logic: if golden and production diverge, it's a bug in
# the golden, not in the business.
#
# EXACT equality, not ±tolerance: OCR is out of this path, so two runs over
# the same inputs give the same number to the peso. A 0.5 % tolerance would
# mask a real regression.
#
# If it BLOCKS, the change does not ship. It isn't a warning: it's a no.
$ python tests/golden_finanzas/eval_finanzas.py check-all [check] ENERO 2026 — VEREDICTO: PASA (5 productos, igualdad exacta) [check] MARZO 2026 — VEREDICTO: PASA (4 productos, igualdad exacta) [check] ABRIL 2026 — VEREDICTO: PASA (3 productos, igualdad exacta) # el gate corre les FUNCIONS REALS del tancament — pivot.calcular_neta_mes() # i pivot.utilidad_mes() — contra tres mesos tancats i verificats a mà. # Sense reimplementar la lògica: si el golden i producció divergeixen, és un bug # del golden, no del negoci. # # Igualtat EXACTA, no ±tolerància: l'OCR queda fora d'aquest camí, així que # dues corregudes sobre els mateixos inputs donen el mateix número al peso. Una # tolerància del 0,5 % emmascararia una regressió real. # # Si BLOQUEJA, el canvi no es tanca. No és un avís: és un no.
El límite honesto del gateThe gate's honest limitEl límit honest del gate

Ningún agente puede verificar que una factura sea real o que un flete sea correcto. Lo que sí es verificable por ejecución es que la cifra es reproducible desde inputs congelados y que cada número dice de dónde sale. El golden comprueba aritmética y trazabilidad, no verdad de negocio: eso lo firma una persona mirando el mes real. El pipe propone; yo confirmo. Y el ground-truth del golden lo fijo yo, no el pipe: si el pipe pudiera reescribirlo para aprobar, el gate sería un sello de goma.

No agent can verify that an invoice is real or that a shipping charge is right. What is verifiable by execution is that the figure is reproducible from frozen inputs and that every number states its source. The golden checks arithmetic and traceability, not business truth: a human signs that off looking at the real month. The pipe proposes; I confirm. And the golden's ground truth is set by me, not by the pipe: if the pipe could rewrite it to pass, the gate would be a rubber stamp.

Cap agent pot verificar que una factura sigui real ni que un port sigui correcte. El que sí és verificable per execució és que la xifra és reproduïble des d'inputs congelats i que cada número diu d'on surt. El golden comprova aritmètica i traçabilitat, no veritat de negoci: això ho signa una persona mirant el mes real. El pipe proposa; jo confirmo. I el ground-truth del golden el fixo jo, no el pipe: si el pipe pogués reescriure'l per aprovar, el gate seria un segell de goma.

Determinismo · pruébalo túDeterminism · try it yourselfDeterminisme · prova-ho tu

El precio de venta no lo decide una IA

The selling price is not decided by an AI

El preu de venda no el decideix una IA

Es aritmética pura: precio = (coste × n + costes_fijos) / (1 − margen), redondeado al siguiente precio psicológico terminado en .900, más un pequeño optimizador que busca la progresión de descuentos más creíble. Cero tokens. Un LLM aquí no aportaría nada y sí podría equivocarse distinto cada vez.

It's pure arithmetic: price = (cost × n + fixed_costs) / (1 − margin), rounded up to the next psychological price ending in .900, plus a small optimiser that finds the most believable discount progression. Zero tokens. An LLM would add nothing here and could get it wrong differently every time.

És aritmètica pura: precio = (coste × n + costes_fijos) / (1 − margen), arrodonit al següent preu psicològic acabat en .900, més un petit optimitzador que busca la progressió de descomptes més creïble. Zero tokens. Un LLM aquí no aportaria res i sí que podria equivocar-se diferent cada vegada.

coste del producto en Dropiproduct cost at Dropicost del producte a Dropi $30.000 COPCOPCOP
x1
$87.900
anteswasabans $200.000 · 55% off
x2
$118.900
descuento mostradodisplayed discountdescompte mostrat 65%
x3
$150.900
descuento mostradodisplayed discountdescompte mostrat 75%
CPA de equilibrio: lo máximo que puedo pagar por una venta antes de perder dinero. Es el número que decide si un anuncio sigue vivo o se apaga. Break-even CPA: the most I can pay for one sale before losing money. It's the number that decides whether an ad stays on or gets killed.CPA d'equilibri: el màxim que puc pagar per una venda abans de perdre diners. És el número que decideix si un anunci segueix viu o s'apaga. $4.967CPA breakeven COPbreak-even CPA, COPCPA breakeven COP
flete basebase shippingport base $17.063 % entregadelivery rate% lliurament 75% admin/pedidoadmin/orderadmin/comanda $2.909 CPA objetivotarget CPACPA objectiu $15.000 margenmarginmarge 5%
Esto no es una maqueta: es el algoritmo de ecxm/predev/precios.py portado a JavaScript línea por línea, incluido el redondeo bancario de Python y el optimizador de progresión de descuentos. Lo verifiqué contra los mismos 7 casos golden que blindan la versión en Python: los 9 campos coinciden al peso en los 7. Los parámetros de arriba son los valores por defecto del repo; en producción se leen del Excel de la tienda. This is not a mock-up: it's the algorithm from ecxm/predev/precios.py ported to JavaScript line by line, including Python's banker's rounding and the discount-progression optimiser. I verified it against the same 7 golden cases that guard the Python version: all 9 fields match to the peso across all 7. The parameters above are the repo defaults; in production they're read from the store's spreadsheet.Això no és una maqueta: és l'algorisme de ecxm/predev/precios.py portat a JavaScript línia per línia, inclòs l'arrodoniment bancari de Python i l'optimitzador de progressió de descomptes. El vaig verificar contra els mateixos 7 casos golden que blinden la versió en Python: els 9 camps coincideixen al peso als 7. Els paràmetres de dalt són els valors per defecte del repo; en producció es llegeixen de l'Excel de la botiga.
7/7

casos golden idénticosidentical golden casescasos golden idèntics

El port JS y el original Python coinciden en los 9 campos, incluidos los bordes (entrega 0 %, CPA explícito).The JS port and the Python original agree on all 9 fields, edge cases included (0 % delivery, explicit CPA).El port JS i l'original Python coincideixen als 9 camps, inclosos els límits (lliurament 0 %, CPA explícit).

0

toleranciatolerancetolerància

Redondeo a 2 decimales solo para neutralizar el ruido del float. Nada más se perdona.Rounding to 2 decimals only to neutralise float noise. Nothing else is forgiven.Arrodoniment a 2 decimals només per neutralitzar el soroll del float. Res més es perdona.

Ingeniería con resultado económicoEngineering with a financial resultEnginyeria amb resultat econòmic

El pipeline que dejó de pagar por pensar

The pipeline that stopped paying to think

El pipeline que va deixar de pagar per pensar

Clonar la landing de un competidor empezó como lo empieza todo el mundo: mandarle capturas a un modelo de visión y pedirle que la reconstruya. Funcionaba, costaba ~$0,05 por landing y era distinto en cada corrida. Hoy el mismo trabajo lo hacen 26 extractores deterministas y 9 parsers de reseñas sobre el HTML real: mismo input, mismo output, $0. Vision sigue ahí, pero solo detrás de un flag explícito, nunca como fallback silencioso.

Cloning a competitor's landing page started the way everyone starts: send screenshots to a vision model and ask it to rebuild the page. It worked, it cost ~$0.05 per landing and it was different on every run. Today the same job is done by 26 deterministic extractors and 9 review parsers over the real HTML: same input, same output, $0. Vision is still there, but only behind an explicit flag, never as a silent fallback.

Clonar la landing d'un competidor va començar com ho comença tothom: enviar-li captures a un model de visió i demanar-li que la reconstrueixi. Funcionava, costava ~$0,05 per landing i era diferent en cada correguda. Avui la mateixa feina la fan 26 extractors deterministes i 9 parsers de ressenyes sobre l'HTML real: mateix input, mateix output, $0. Vision hi segueix, però només darrere d'un flag explícit, mai com a fallback silenciós.

5

plataformas cubiertasplatforms coveredplataformes cobertes

Shopify, Funnelish, GemPages, Pagefly y Tiendanube, cada una con su forma de esconder el mismo contenido.Shopify, Funnelish, GemPages, Pagefly and Tiendanube, each hiding the same content its own way.Shopify, Funnelish, GemPages, Pagefly i Tiendanube, cadascuna amb la seva manera d'amagar el mateix contingut.

27

landings de regresiónregression landingslandings de regressió

Un set real de competidores. Se regeneran una a una y se diffea el HTML: el validator en verde no basta.A real competitor set. Regenerated one by one with an HTML diff: a green validator isn't enough.Un set real de competidors. Es regeneren una a una i es fa diff de l'HTML: el validator en verd no n'hi ha prou.

4

goldens congeladosfrozen goldensgoldens congelats

Partidos por zona (copy · CSS · footer) y con las URLs normalizadas, para que el diff detecte drift y no ruido.Split by zone (copy · CSS · footer) with normalised URLs, so the diff catches drift, not noise.Partits per zona (copy · CSS · footer) i amb les URLs normalitzades, perquè el diff detecti drift i no soroll.

8.549

líneas del extractorextractor lineslínies de l'extractor

El precio real de la determinación: cada caso raro de cada builder, escrito y cubierto por el set.The real price of determinism: every builder's weird case, written down and covered by the set.El preu real de la determinació: cada cas rar de cada builder, escrit i cobert pel set.

# el gate no avisaba: dejaba pasar # replicar_plantilla.py, durante 11 días report = validar_landing(output_dir) if not report.passed: print("[WARN] la réplica tiene fallos") # "no abortamos un generado # imperfecto, solo avisamos" # ── después ────────────────────────── if not report.passed: raise ReplicaValidatorFailed( output_dir, report.failures) # CLI → exit 1 · dashboard → captura la # excepción y expone el HTML para debug
# the gate didn't warn: it let things through # replicar_plantilla.py, for 11 days report = validar_landing(output_dir) if not report.passed: print("[WARN] the replica has failures") # "we don't abort an imperfect # build, we just warn" # ── after ──────────────────────────── if not report.passed: raise ReplicaValidatorFailed( output_dir, report.failures) # CLI → exit 1 · dashboard → catches the # exception and exposes the HTML to debug
# el gate no avisava: deixava passar # replicar_plantilla.py, durant 11 dies report = validar_landing(output_dir) if not report.passed: print("[WARN] la réplica tiene fallos") # "no avortem un generat # imperfecte, només avisem" # ── després ────────────────────────── if not report.passed: raise ReplicaValidatorFailed( output_dir, report.failures) # CLI → exit 1 · dashboard → captura l' # excepció i exposa l'HTML per depurar

El validator existía desde hacía semanas, con su lista de placeholders prohibidos y sus checks de estructura. Y aun así, once días de landings con fallos pasaron el gate, porque el gate solo imprimía un warning.

Una defensa que solo avisa entrena a su dueño a ignorarla. Hoy la regla del repo es explícita: toda defensa nueva tiene que abortar: exit ≠ 0, raise, o un fallo detectable aguas abajo. Si hace falta no bloquear en un caso concreto, se hace con un flag visible, no con silencio por defecto.

El mismo principio arregló otro fallo más sutil: un sys.exit() dentro de una librería lanza SystemExit, que no hereda de Exception, así que atravesaba todos los except Exception del dashboard y se llevaba por delante la interfaz entera.

The validator had existed for weeks, with its forbidden-placeholder list and its structure checks. And still, eleven days of broken landings sailed through the gate, because the gate only printed a warning.

A defense that merely warns trains its owner to ignore it. The repo rule is now explicit: every new defense must abort: exit ≠ 0, raise, or a failure detectable downstream. If a specific case genuinely shouldn't block, that's done with a visible flag, not with silence by default.

The same principle fixed a subtler failure: a sys.exit() inside a library raises SystemExit, which doesn't inherit from Exception, so it sailed straight through every except Exception in the dashboard and took the whole UI down.

El validator existia des de feia setmanes, amb la seva llista de placeholders prohibits i els seus checks d'estructura. I tot i així, onze dies de landings amb fallades van passar el gate, perquè el gate només imprimia un warning.

Una defensa que només avisa entrena el seu amo a ignorar-la. Avui la regla del repo és explícita: tota defensa nova ha d'avortar: exit ≠ 0, raise, o una fallada detectable aigües avall. Si cal no bloquejar en un cas concret, es fa amb un flag visible, no amb silenci per defecte.

El mateix principi va arreglar una altra fallada més subtil: un sys.exit() dins d'una llibreria llança SystemExit, que no hereta d'Exception, així que travessava tots els except Exception del dashboard i s'enduia per davant la interfície sencera.

Lo que decidí NO construirWhat I decided NOT to buildEl que vaig decidir NO construir

Decisiones medidas, no intuidas

Measured decisions, not guessed

Decisions mesurades, no intuïdes

El activo que no se puede fingir no es el código: es el juicio. Cada una de estas ideas era razonable y tentadora; todas murieron con un dato concreto delante. Varias iban en contra de lo que yo quería que fuera verdad, y por eso están aquí.

The asset you can't fake isn't the code: it's judgment. Every one of these ideas was reasonable and tempting; all of them died with a concrete piece of data in front of them. Several went against what I wanted to be true, which is exactly why they're here.

L'actiu que no es pot fingir no és el codi: és el criteri. Cadascuna d'aquestes idees era raonable i temptadora; totes van morir amb una dada concreta al davant. Diverses anaven en contra del que jo volia que fos veritat, i per això són aquí.

IdeaIdeaIdea Por qué tentabaWhy it temptedPer què temptava Qué encontréWhat I foundQuè vaig trobar VeredictoVerdictVeredicte
CSV de Meta como fuente de costeMeta CSV as the cost sourceCSV de Meta com a font de costun solo archivo con todo el gasto del mesone file with the whole month's spendun sol fitxer amb tota la despesa del mes un download y listo, sin OCRone download and done, no OCRun download i llestos, sense OCR sin desglose por campaña ni estado Pagado/Error; los PDFs sí lo traenno per-campaign breakdown, no Paid/Error state; the PDFs have bothsense desglossament per campanya ni estat Pagat/Error; els PDFs sí que ho porten Descartado como costeRuled out as costDescartat com a cost
Contar el flete de todos los pedidosCount shipping on every orderComptar el port de totes les comandesal fin y al cabo es flete que se pagaafter all, it's shipping that gets paidal capdavall és port que es paga parecía más conservadorit looked more conservativesemblava més conservador la suma por producto dejaba de cuadrar con el total del mesthe per-product sum stopped matching the month totalla suma per producte deixava de quadrar amb el total del mes Solo 4 estatus finalesFinal 4 statuses onlyNomés 4 estats finals
Vision para clonar reseñasVision to clone reviewsVision per clonar ressenyescada competidor pinta sus reseñas distintoevery competitor renders reviews differentlycada competidor pinta les seves ressenyes diferent «un modelo lo resuelve todo»"one model solves everything"«un model ho resol tot» 9 parsers cubren el set entero; sin parser → sección omitida, no invención9 parsers cover the whole set; no parser → section omitted, nothing invented9 parsers cobreixen el set sencer; sense parser → secció omesa, no invenció Fuera del pipe · $0Out of the pipe · $0Fora del pipe · $0
Servidor, n8n, FastAPI, PostgresServer, n8n, FastAPI, PostgresServidor, n8n, FastAPI, Postgresla arquitectura «seria»the "serious" architecturel'arquitectura «seriosa» se ve mejor en un diagramait looks better on a diagrames veu millor en un diagrama 5–15 tests/semana y un operador → infra sin usuarios y con mantenimiento5–15 tests/week and one operator → infra with no users and real upkeep5–15 tests/setmana i un operador → infra sense usuaris i amb manteniment Local + SQLiteLocal + SQLiteLocal + SQLite
Tasa 1.0 para divisa desconocida1.0 rate for unknown currencyTaxa 1.0 per a divisa desconegudaasí el importe nunca sale vacíothat way the amount is never emptyaixí l'import mai surt buit una tabla sin huecos da confianzaa table with no gaps feels trustworthyuna taula sense forats dona confiança subestimaba un coste en USD ~4.200× → podía convertir un perdedor en winnerunderstated a USD cost ~4,200× → could turn a loser into a winnersubestimava un cost en USD ~4.200× → podia convertir un perdedor en winner None + avisowarningavís
Borrar la caché de LLM al cambiar un promptWipe the LLM cache on prompt changeEsborrar la memòria cau d'LLM en canviar un prompt«está sucia, mejor empezar limpio»"it's dirty, better start clean"«està bruta, millor començar net» higiene aparenteapparent hygienehigiene aparent 268 entradas borradas = 268 llamadas ya pagadas que hubo que repagar268 entries deleted = 268 already-paid calls that had to be paid again268 entrades esborrades = 268 crides ja pagades que es van haver de repagar Nunca sin permisoNever without askingMai sense permís
Forzar COP en la publicidadForce COP on ad spendForçar COP a la publicitathoy todas las cuentas facturan en pesostoday every account bills in pesosavui tots els comptes facturen en pesos funciona… hasta que deje de hacerloit works… until it doesn'tfunciona… fins que deixi de fer-ho la primera cuenta que facture en USD escondería un ×4.200 sin avisarthe first USD-billing account would silently hide a ×4,200el primer compte que facturi en USD amagaria un ×4.200 sense avisar Riesgo documentadoDocumented riskRisc documentat

La última fila no es un fallo mío que se me olvidó: es un footgun conocido, escrito y fechado en el backlog, con la condición exacta que lo disparará. Prefiero un riesgo documentado y visible a un riesgo resuelto a medias en silencio.

That last row isn't a mistake I forgot about: it's a known footgun, written down and dated in the backlog, with the exact condition that will trigger it. I'd rather have a documented, visible risk than one half-fixed in silence.

L'última fila no és una fallada meva que se'm va oblidar: és un footgun conegut, escrit i datat al backlog, amb la condició exacta que el dispararà. Prefereixo un risc documentat i visible a un risc resolt a mitges en silenci.

Arquitectura · WATArchitecture · WATArquitectura · WAT

La IA razona; el código determinista ejecuta

The AI reasons; deterministic code executes

La IA raona; el codi determinista executa

Todo el repo está montado sobre una idea aritmética muy simple: si cada paso de una cadena es un 90 % fiable, cinco pasos seguidos te dejan en 59 %. Por eso la IA no ejecuta: orquesta. Las instrucciones viven en workflows en markdown, el juicio lo pone el agente, y el trabajo real lo hacen scripts de Python testeables y repetibles.

The whole repo rests on one very simple piece of arithmetic: if each step in a chain is 90 % reliable, five steps in a row leave you at 59 %. That's why the AI doesn't execute: it orchestrates. Instructions live in markdown workflows, judgment comes from the agent, and the real work is done by testable, repeatable Python scripts.

Tot el repo està muntat sobre una idea aritmètica molt simple: si cada pas d'una cadena és un 90 % fiable, cinc passos seguits et deixen en 59 %. Per això la IA no executa: orquestra. Les instruccions viuen en workflows en markdown, el criteri el posa l'agent, i la feina real la fan scripts de Python testejables i repetibles.

CAPA 01 · WORKFLOWS

Las instruccionesThe instructionsLes instruccions

SOPs en markdown: objetivo, entradas necesarias, qué herramienta usar y cómo tratar los casos raros. Escritos como se le explica a una persona del equipo, y actualizados cuando el proceso aprende algo.Markdown SOPs: objective, required inputs, which tool to use and how to handle edge cases. Written the way you'd brief a teammate, and updated whenever the process learns something.SOPs en markdown: objectiu, entrades necessàries, quina eina fer servir i com tractar els casos rars. Escrits com se li explica a una persona de l'equip, i actualitzats quan el procés aprèn alguna cosa.

CAPA 02 · AGENTE

La decisiónThe decisionLa decisió

Lee el workflow, encadena las herramientas en el orden correcto, se recupera de los errores y pregunta cuando falta información. No calcula precios ni conmuta números: conecta intención con ejecución.Reads the workflow, chains the tools in the right order, recovers from errors and asks when information is missing. It doesn't compute prices or crunch numbers: it connects intent to execution.Llegeix el workflow, encadena les eines en l'ordre correcte, es recupera dels errors i pregunta quan falta informació. No calcula preus ni commuta números: connecta intenció amb execució.

CAPA 03 · HERRAMIENTAS

La ejecuciónThe executionL'execució

~34.500 líneas de Python en ecxm/: scraping, pandas, openpyxl, OCR, generación. Consistentes, rápidas y testeables. Toda llamada a un modelo pasa por core/llm.py: un único punto que cachea por hash y contabiliza el coste.~34,500 lines of Python in ecxm/: scraping, pandas, openpyxl, OCR, generation. Consistent, fast and testable. Every model call goes through core/llm.py: a single point that caches by hash and accounts for cost.~34.500 línies de Python a ecxm/: scraping, pandas, openpyxl, OCR, generació. Consistents, ràpides i testejables. Tota crida a un model passa per core/llm.py: un únic punt que fa cau per hash i comptabilitza el cost.

LA CADENA (la salida de cada pipe es la entrada del siguiente THE CHAIN) each pipe's output is the next one's inputLA CADENA (la sortida de cada pipe és l'entrada del següent SNIPE Ads Library · PlaywrightAds Library · PlaywrightAds Library · Playwright LAB precios · copy · títulospricing · copy · titlespreus · copy · títols REP réplica de landing · $0landing replica · $0rèplica de landing · $0 CREATIVE estáticos · vídeo · UGCstatics · video · UGCestàtics · vídeo · UGC ANALYTICS reglas · $0 LLMrules · $0 LLMregles · $0 LLM FINANZASFINANCEFINANCES irreversible · el cierreirreversible · the closeirreversible · el tancament /eval-finanzas SUPERFICIE COMPARTIDASHARED SURFACESUPERFÍCIE COMPARTIDA un único dashboard de 17.296 líneas · session_state global · CSS y JS globales · constantes y helpers comunes one 17,296-line dashboard · global session_state · global CSS and JS · shared constants and helpersun únic dashboard de 17.296 línies · session_state global · CSS i JS globals · constants i helpers comuns COMPES_TRACKER.xlsx · ecxm.db · fb_cookies.json · dashboard_state.json cada línea punteada es una vía por la que un cambio en UNA pestaña puede romper OTRA every dotted line is a path by which a change in ONE tab can break ANOTHERcada línia puntejada és una via per la qual un canvi en UNA pestanya pot trencar-ne UNA ALTRA por eso existe dashboard_map.json: qué hace cada pestaña, con qué se sincroniza y QUÉ SE ROMPE al tocarla hence dashboard_map.json: what each tab does, what it syncs with and WHAT BREAKS when you touch itper això existeix dashboard_map.json: què fa cada pestanya, amb què se sincronitza i QUÈ ES TRENCA en tocar-la se lee ANTES de editar y se actualiza DESPUÉS (es la fuente de verdad, no un diagrama decorativo read BEFORE editing and updated AFTER) it's the source of truth, not a decorative diagrames llegeix ABANS d'editar i s'actualitza DESPRÉS (és la font de veritat, no un diagrama decoratiu Cross-Pipe Safety · ninguna tarea se cierra sin comprobar que los demás pipes siguen vivos Cross-Pipe Safety · no task closes without checking the other pipes are still aliveCross-Pipe Safety · cap tasca es tanca sense comprovar que els altres pipes segueixen vius un bug en SNIPE que rompe el pipe de réplicas cuesta más en diagnóstico que el cambio original en desarrollo a bug in SNIPE that breaks the replica pipe costs more to diagnose than the original change cost to buildun bug a SNIPE que trenca el pipe de rèpliques costa més en diagnòstic que el canvi original en desenvolupament

Pellizca para acercar y leer el detalle ↔Pinch to zoom in and read the detail ↔Pessiga per apropar i llegir el detall ↔

Calibrado de ceremoniaCeremony calibrationCalibratge de cerimònia

El riesgo lo marca la superficie, no el tamaño del diff

Risk is set by the surface, not by the size of the diff

El risc el marca la superfície, no la mida del diff

Un cambio de dos líneas en el cierre de finanzas es más peligroso que refactorizar quinientas de estilos. Por eso el proceso no se calibra por líneas cambiadas sino por dónde se toca, y ese conjunto de superficies es inmutable: no lo puede ampliar ni relajar ningún proceso automático.

A two-line change in the finance close is more dangerous than refactoring five hundred lines of styling. So the process is calibrated not by lines changed but by where you touch, and that set of surfaces is immutable: no automated process can widen or relax it.

Un canvi de dues línies al tancament de finances és més perillós que refactoritzar-ne cinc-centes d'estils. Per això el procés no es calibra per línies canviades sinó per on es toca, i aquest conjunt de superfícies és immutable: no el pot ampliar ni relaxar cap procés automàtic.

IrreversibleIrreversibleIrreversible

El cierre de mesThe month closeEl tancament de mes

Ahí el número se convierte en un pago. También cuenta borrar la caché de LLM ya pagada y romper la convención de nombres de campaña.That's where the number becomes a payment. Also: deleting already-paid LLM cache, and breaking the campaign naming convention.Allà el número es converteix en un pagament. També compta esborrar la memòria cau d'LLM ja pagada i trencar la convenció de noms de campanya.

ritual completo + doble pase independientefull ritual + independent second passritual complet + doble passada independent
Sensible · reversibleSensitive · reversibleSensible · reversible

Réplicas, pivot, dashboardReplicas, pivot, dashboardRèpliques, pivot, dashboard

Duele si se rompe, pero se recupera. Aquí el gate ya existe: validator, golden y set de regresión.It hurts when it breaks, but it recovers. The gate already exists here: validator, golden and regression set.Fa mal si es trenca, però es recupera. Aquí el gate ja existeix: validator, golden i set de regressió.

ceremonia media + gate automáticomedium ceremony + automated gatecerimònia mitjana + gate automàtic
No sensibleNot sensitiveNo sensible

Precios, copy de UI, estilosPricing, UI copy, stylingPreus, copy d'UI, estils

Recomputable y visible al instante. Aquí el proceso pesado sería teatro: leer, cambiar, verificar y decirlo.Recomputable and instantly visible. Heavy process here would be theatre: read, change, verify, say so.Recomputable i visible a l'instant. Aquí el procés pesat seria teatre: llegir, canviar, verificar i dir-ho.

ceremonia mínimaminimal ceremonycerimònia mínima
Cómo trabajo con IAHow I work with AICom treballo amb IA

El modo de fallo real no es planificar mal: es reportar sin verificar

The real failure mode isn't bad planning: it's reporting without verifying

El mode de fallada real no és planificar malament: és reportar sense verificar

Ningún «el subagente reportó OK» cierra nada aquí: el orquestador corre él mismo el gate y pega la salida real en el prompt del siguiente paso.

No "the subagent reported OK" closes anything here: the orchestrator runs the gate itself and pastes the real output into the next step's prompt.

Cap «el subagent ha reportat OK» tanca res aquí: l'orquestrador corre ell mateix el gate i enganxa la sortida real al prompt del pas següent.

los otros dos gates · el de finanzas está arribathe other two gates · the finance one is aboveels altres dos gates · el de finances és a dalt
$ python tests/golden_precios/eval_precios.py check
[check] precios — VEREDICTO: PASA (7 casos, igualdad exacta)

$ python tests/golden_control_diario/eval_control_diario.py check
[check] control_diario — VEREDICTO: PASA (6 casos, igualdad exacta)

# Los goldens con cifras reales del negocio NO se versionan: el arnés se
# comparte, cada máquina captura su propio baseline. Sin baseline el gate
# ni aprueba ni bloquea — avisa de que falta. Un gate que aprueba en vacío
# es peor que no tener gate.
$ python tests/golden_precios/eval_precios.py check
[check] pricing — VERDICT: PASS (7 cases, exact equality)

$ python tests/golden_control_diario/eval_control_diario.py check
[check] control_diario — VERDICT: PASS (6 cases, exact equality)

# Goldens holding real business figures are NOT versioned: the harness is
# shared, each machine captures its own baseline. With no baseline the gate
# neither passes nor blocks — it reports the baseline is missing. A gate that
# passes on nothing is worse than no gate at all.
$ python tests/golden_precios/eval_precios.py check [check] precios — VEREDICTO: PASA (7 casos, igualdad exacta) $ python tests/golden_control_diario/eval_control_diario.py check [check] control_diario — VEREDICTO: PASA (6 casos, igualdad exacta) # Els goldens amb xifres reals del negoci NO es versionen: l'arnès es # comparteix, cada màquina captura el seu propi baseline. Sense baseline el gate # ni aprova ni bloqueja — avisa que falta. Un gate que aprova en buit # és pitjor que no tenir gate.

Verificación por ejecuciónVerification by executionVerificació per execució

Verde local ≠ correcto. Que el dashboard arranque no dice nada sobre si la utilidad neta que calculó el pivot es la real. La única señal con dientes es el gate golden, y lo corro yo antes de cerrar nada.Green locally ≠ correct. The dashboard booting says nothing about whether the net profit the pivot computed is the real one. The only signal with teeth is the golden gate, and I run it myself before closing anything.Verd local ≠ correcte. Que el dashboard arrenqui no diu res sobre si la utilitat neta que va calcular el pivot és la real. L'únic senyal amb dents és el gate golden, i el corro jo abans de tancar res.

Un bug nunca vive soloA bug never lives aloneUn bug mai viu sol

Al encontrar un fallo, la pregunta obligatoria es: ¿existe el mismo bug en los caminos análogos? Un invariante como «el flete solo cuenta en los 4 estatus finales» vive en un sitio y lo llaman todas las etapas: ingerir, limpiar, cruzar, pivotar y cerrar.On finding a defect, the mandatory question is: does the same bug exist in the analogous paths? An invariant like "shipping only counts on the 4 final statuses" lives in one place and is called by every stage: ingest, clean, cross-match, pivot and close.En trobar una fallada, la pregunta obligatòria és: existeix el mateix bug als camins anàlegs? Un invariant com «el port només compta als 4 estats finals» viu en un lloc i el criden totes les etapes: ingerir, netejar, creuar, pivotar i tancar.

Lo que sigue abierto

What's still open

El que segueix obert

El sistema está en producción y se usa todos los días, pero no está «terminado», y decir lo contrario sería el primer número falso de esta página.

The system is in production and used every day, but it isn't "finished", and saying otherwise would be the first false number on this page.

El sistema està en producció i es fa servir cada dia, però no està «acabat», i dir el contrari seria el primer número fals d'aquesta pàgina.

aplazado a propósitodeliberately deferredajornat a propòsitAuditoría integral del dashboard. Con 17.296 líneas en un solo archivo, una auditoría hecha a trozos genera más ruido que señal. Decisión tomada y fechada: esperar y hacer una sola pasada acotada, con tres focos definidos.Full dashboard audit. At 17,296 lines in a single file, a piecemeal audit generates more noise than signal. Decision made and dated: wait and do a single scoped pass with three defined focuses.Auditoria integral del dashboard. Amb 17.296 línies en un sol fitxer, una auditoria feta a trossos genera més soroll que senyal. Decisió presa i datada: esperar i fer una sola passada acotada, amb tres focus definits.
riesgo conocidoknown riskrisc conegutForzado de divisa en publicidad. Hoy inocuo porque todas las cuentas facturan en pesos; se disparará con la primera que facture en dólares. Está escrito, con su condición de disparo, esperando el arreglo correcto en lugar de un parche.Currency forcing on ad spend. Harmless today because every account bills in pesos; it will fire with the first one billing in dollars. It's written down, with its trigger condition, waiting for the right fix instead of a patch.Forçat de divisa en publicitat. Avui inocu perquè tots els comptes facturen en pesos; es dispararà amb el primer que facturi en dòlars. Està escrit, amb la seva condició de dispar, esperant l'arranjament correcte en lloc d'un pedaç.
cobertura parcialpartial coveragecobertura parcialGoldens de landing. 4 congelados de 27 landings del set de regresión. Los tres canónicos cubren los builders más frágiles; el resto se compara por diff, que detecta cambios pero no juzga si son correctos.Landing goldens. 4 frozen out of the 27 landings in the regression set. The three canonical ones cover the most fragile builders; the rest are compared by diff, which detects changes but doesn't judge whether they're right.Goldens de landing. 4 congelats de 27 landings del set de regressió. Els tres canònics cobreixen els builders més fràgils; la resta es compara per diff, que detecta canvis però no jutja si són correctes.

El resto del método (el agente ciego que audita mis planes, el ledger que convierte un fallo en regla) es el mismo en los cinco sistemas y está contado una vez: en el índice.The rest of the method (the blind agent auditing my own plans, the ledger that turns a failure into a rule) is the same across all five systems and is told once: on the index.La resta del mètode (l'agent cec que audita els meus plans, el ledger que converteix una fallada en regla) és el mateix als cinc sistemes i està explicat una vegada: a l'índex.

Disponible para trabajarAvailable for workDisponible per treballar

Cojo un negocio entero, lo descompongo en pipelines y orquesto IA para construir cada pieza, sin perder el rigor donde hay dinero.

I take an entire business, break it into pipelines and orchestrate AI to build every piece, without losing rigor where money is involved.

Agafo un negoci sencer, el descomponc en pipelines i orquestro IA per construir cada peça, sense perdre el rigor on hi ha diners.

Si buscas a alguien para applied-AI, automatización de operaciones o forward-deployed engineering, que construye sistemas para que la IA no se engañe a sí misma ni a ti, hablemos.

If you're looking for someone in applied-AI, operations automation or forward-deployed engineering who builds systems so the AI can't fool itself or you, let's talk.

Si busques algú per a applied-AI, automatització d'operacions o forward-deployed engineering, que construeix sistemes perquè la IA no s'enganyi a si mateixa ni a tu, parlem-ne.

Todo lo de esta página lo construí en solitario, con IA y sin formación técnica previa.Everything on this page I built solo, with AI and with no prior technical background.Tot el d'aquesta pàgina ho vaig construir en solitari, amb IA i sense formació tècnica prèvia.

ECXM OPS · Diego · 2026 Sistema en producción · construido con IASystem in production · built with AISistema en producció · construït amb IA