diff --git a/AGENTS.md b/AGENTS.md
index 6100b1b..c802b38 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -14,8 +14,13 @@
src/
├── assets/ # Imágenes, iconos estáticos
├── components/ # Componentes Vue reutilizables
+│ ├── order/ # Componentes del resumen de pedido público
+│ ├── provenance/ # Provenance (público + admin): gráficos, sección y CRUD admin
+│ │ └── admin/ # Organizaciones, Proveedores, Geografía, SupplierLinkDialog
+│ └── graph/ # CytoscapeChart.vue (wrapper genérico de cytoscape)
├── layouts/ # Layouts de página
├── pages/ # Vistas (auto-routed desde文件名)
+│ └── admin/ # Páginas admin (products, organizations, suppliers, geography, ...)
├── plugins/ # Configuración de Vuetify, etc.
├── router/ # Configuración de rutas
├── services/ # API services (auth.js, etc.)
@@ -23,6 +28,7 @@ src/
│ ├── api-implementation.js # Factory que selecciona implementación
│ ├── auth.js # Manejo de auth (login, tokens JWT)
│ ├── django-api.js # Implementación de API para Django
+│ ├── graph/ # Genérico de grafos: graph-layout.js (layout por columnas + cytoscape)
│ └── http.js # Axios instance con interceptors
├── stores/ # Pinia stores
└── styles/ # SCSS settings
@@ -89,12 +95,16 @@ No hay un estilo mayoritario. El código histórico está partido:
### Config de ESLint
- `.eslintrc.js` está **versionado** y extiende `vuetify` (estilo **StandardJS**)
- Tiene `ignorePatterns` masivo: `src/**` excepto los archivos nuevos de la tarea
- (`!src/components/order/**`, `!src/components/PublicOrderSummary.vue`, `!src/pages/pedido/**`)
+ (`!src/components/order/**`, `!src/components/PublicOrderSummary.vue`,
+ `!src/components/provenance/**`, `!src/components/graph/*.vue`,
+ `!src/services/graph/*.js`, `!src/pages/pedido/**`)
- **Los archivos nuevos deben seguir StandardJS** para quedar lint-eados:
- 2 espacios (indent), sin semicolons, comillas simples
- `function () {}` con espacio, `const f = (x) => x` (arrow-parens en args únicos NO)
- Sin trailing commas; `{ clave: valor }` con espacios internos
- Eventos personalizados en kebab-case, `v-slot:nombre` (no `#nombre`)
+ - Atributos en orden alfabético dentro de su categoría (`vue/attributes-order`):
+ directivas (`v-if`, `v-model`) primero, luego props/attrs, luego `@eventos`
### PELIGRO: `npm run lint` usa `--fix`
- Reformatea automáticamente TODO archivo no ignorado que no cumpla estilo
@@ -109,6 +119,9 @@ No hay un estilo mayoritario. El código histórico está partido:
- Los tests **no usan globals**: importar `describe/it/expect/vi` explícitamente desde `vitest`
- Tests de páginas con router: esperar a que el router actualice `route.params` con un helper (`waitForRouteParam`)
- Los `.d.ts` generados (`auto-imports.d.ts`, `components.d.ts`, `typed-router.d.ts`) están en `.gitignore`
+- **Diálogos Vuetify se teleportan a `document.body`**: en tests, el contenido NO está en `wrapper.text()`. Assertar sobre `document.body.textContent` (ver `tests/unit/components/provenance/ProvenanceDetailModal.spec.js`). Helpers para interactuar con inputs/buttons de diálogos en `tests/unit/components/provenance/admin/helpers.js` (`setBodyInput`, `clickBody`)
+- **Selects/autocompletados en tests**: escribir en su `` NO cambia el `v-model`. Emitir `update:modelValue` sobre el componente (`findAllComponents({ name: 'VSelect' })` / `{ name: 'VAutocomplete' }`). OJO: `VAutocomplete` también matchea como `VSelect`, y `v-data-table` añade un `VSelect` (items-per-page); filtrar por `props('items')` cuando haya varios
+- **Listas largas** (municipios, proveedores): `v-autocomplete` con búsqueda, pero la selección debe conservarse aunque el filtro no la incluya → `items` computado que devuelve los filtrados + los seleccionados que no estén (patrón en `SuppliersManagement.vue`, `GeographyManagement.vue`, `SupplierLinkDialog.vue`)
## Common Issues
1. **Página en blanco:** Verificar que los componentes en `src/pages/*.vue` tengan import explícito
@@ -159,3 +172,14 @@ No hay un estilo mayoritario. El código histórico está partido:
- `getPublicOrderSummary(code)` en `services/api.js` / `django-api.js`
- Componentes modulares en `src/components/order/`: `OrderAccessInfo.vue` (código + link), `OrderCustomer.vue`, `OrderLines.vue`, `OrderPayment.vue`, `OrderTotal.vue`
- Orquestador: `PublicOrderSummary.vue`; `OrderAccessInfo.vue` se comparte con `SummaryPurchase.vue`
+
+## Provenance (Origen e historia de los productos)
+- Los gráficos se renderizan en el resumen público (`ProvenanceSection` dentro de `PublicOrderSummary.vue`) a partir de `product_provenance` embebido en el resumen (`GET /don_confiao/resumen_publico/`). El backend NO genera los gráficos.
+- Payload: `[{ product: {id, name, catalogue_images[]}, suppliers: [{ supplier: {...}, organization|null, municipality|null, department|null, country|null }] }]`.
+- **Genérico reutilizable:**
+ - `src/services/graph/graph-layout.js`: `computeColumnLayout` (layout por columnas puro) y `toCytoscapeElements` (adapta nodos/aristas a cytoscape, añade clase `has-image` si el nodo tiene imagen)
+ - `src/components/graph/CytoscapeChart.vue`: wrapper de cytoscape.js (props `elements`, `styles` (map a `style` en cytoscape), `layout`, `height`; emite `select` con `node.data()`)
+- **Específico público** (`src/components/provenance/`): builders puros en `provenance-graph.js` (`buildSupplierOrganizationGraph`, `buildTerritoryGraph`, `hasAnySupplier`, `hasAnyTerritory`), los charts (que muestran "próximamente estará disponible" cuando no hay relaciones), `ProvenanceDetailModal.vue` y `ProvenanceSection.vue`
+- **Admin CRUD** (`src/components/provenance/admin/`): `OrganizationsManagement.vue`, `SuppliersManagement.vue`, `GeographyManagement.vue` (tabs países/departamentos/municipios), `SupplierLinkDialog.vue` (vincula productos↔proveedores, abierto desde `ProductsManagement.vue`). Páginas en `src/pages/admin/{organizations,suppliers,geography}.vue`; rutas en `ADMIN_ROUTES` (`router/index.js`); ítems en `NavBar.vue`
+- **Endpoints provenance**: `/don_confiao/api/organizations/`, `/suppliers/`, `/countries/`, `/departments/`, `/municipalities/` (CRUD); vincular productos con `PATCH /don_confiao/api/products//` body `{"suppliers": [ids]}`; detalle de producto (con `suppliers`) via `GET /don_confiao/api/products//`
+- Los tests mockean cytoscape (`vi.mock('cytoscape', ...)`) y la API con `global.provide: { api }`