---
name: shopify-taxonomia-productos
description: "Asigna a cada producto una categoría de la Taxonomía estándar de productos de Shopify para que los agentes de IA relacionen lo que busca el comprador con la categoría correcta. Úsala cuando tengas productos sin categoría o mal categorizados."
---

## Propósito
Los agentes de compra con IA convierten una búsqueda («tenis para correr», «silla de oficina», «tenis sostenibles») en un nodo de la taxonomía y luego traen los productos de ese nodo. Los productos sin categoría de la Taxonomía estándar de productos quedan por fuera de esa relación: solo aparecen si por suerte coinciden las palabras exactas. Esta skill encuentra los productos sin categoría (o mal categorizados) y les asigna la categoría correcta de la taxonomía estándar de Shopify, deducida a partir del título, el tipo y las etiquetas, y confirmada contra el árbol de taxonomía vigente. Corrige los productos sin categoría de la taxonomía y mejora la coincidencia entre tu catálogo y lo que buscan los compradores.

## Requisitos
- Sesión autenticada de Shopify CLI: `shopify store auth --store <tu-tienda>.myshopify.com --scopes read_products,write_products`
- Las consultas se ejecutan con `shopify store execute`.
- Permisos (scopes) de API necesarios: `read_products`, `write_products`

## Parámetros
Todas las skills aceptan estos parámetros generales:

| Parámetro | Tipo   | Obligatorio | Predeterminado | Descripción |
|-----------|--------|-------------|----------------|-------------|
| store     | string | sí          | —              | Dominio de la tienda (p. ej., mitienda.myshopify.com) |
| format    | string | no          | human          | Formato de salida: `human` (predeterminado) o `json` |
| dry_run   | bool   | no          | false          | Muestra las mutaciones sin ejecutarlas |

Parámetros propios de esta skill:

| Parámetro | Tipo | Obligatorio | Predeterminado | Descripción |
|-----------|------|-------------|----------------|-------------|
| collection_id | string | no | — | Limita a una colección (GID) |
| tag | string | no | — | Limita a una etiqueta de producto |
| only_missing | bool | no | true | Si es true, solo asigna categoría a los productos que no tienen; si es false, también revisa las que no coinciden |
| confidence_floor | float | no | 0.7 | Omite los productos cuya mejor coincidencia en la taxonomía tenga un puntaje menor a este |

## Seguridad

> ⚠️ El paso 4 (`productUpdate`) asigna la `category` a productos publicados, y eso afecta los filtros de la tienda en línea, los marketplaces y los impuestos. Una categoría equivocada archiva mal el producto en todas partes. Ejecuta con `dry_run: true`, revisa la relación propuesta `producto → categoría` y asigna automáticamente solo las coincidencias por encima de `confidence_floor`; deja el resto en cola para revisión humana.

## Pasos

1. **OPERACIÓN:** `products` — consulta
   **Entradas:** `first: 250`, filtro opcional; campos `title`, `productType`, `tags`, `category{ id fullName }`; pagina los resultados.
   **Resultado esperado:** Los productos con su categoría actual (o null).

2. **OPERACIÓN:** `taxonomy` — consulta
   **Entradas:** busca en el árbol de la taxonomía estándar con términos candidatos sacados del tipo y el título de cada producto.
   **Resultado esperado:** Nodos de categoría candidatos de la taxonomía (id + fullName) para comparar.

3. **CÁLCULO (sin API):** califica cada producto contra los nodos candidatos y elige el mejor que sea ≥ `confidence_floor`. Muestra la relación propuesta.

4. **OPERACIÓN:** `productUpdate` — mutación
   **Entradas:** `{ id, category: <taxonomyCategoryId> }` por cada coincidencia confiable.
   **Resultado esperado:** Categoría del producto actualizada; recoge los `userErrors`.

## Operaciones GraphQL

```graphql
# products:query — validada con api_version 2025-01
query TaxonomyProducts($first: Int!, $after: String, $query: String) {
  products(first: $first, after: $after, query: $query) {
    edges {
      node {
        id
        title
        productType
        tags
        category { id fullName }
      }
    }
    pageInfo { hasNextPage endCursor }
  }
}
```

```graphql
# taxonomy:query — validada con api_version 2025-01
query TaxonomySearch($search: String) {
  taxonomy {
    categories(first: 20, search: $search) {
      edges { node { id fullName isLeaf level } }
    }
  }
}
```

```graphql
# productUpdate:mutation — validada con api_version 2025-01
mutation TaxonomyAssign($input: ProductInput!) {
  productUpdate(input: $input) {
    product { id category { id fullName } }
    userErrors { field message }
  }
}
```

## Seguimiento de la sesión

**Claude DEBE mostrar lo siguiente en cada etapa. Es obligatorio.**

**Al iniciar**, muestra:
```
╔══════════════════════════════════════════════╗
║  SKILL: <nombre de la skill>                 ║
║  Tienda: <dominio de la tienda>              ║
║  Inicio: <AAAA-MM-DD HH:MM UTC>              ║
╚══════════════════════════════════════════════╝
```

**Después de cada paso**, muestra:
```
[N/TOTAL] <CONSULTA|MUTACIÓN>  <OperationName>
          → Parámetros: <resumen breve de las entradas clave>
          → Resultado: <cantidad o desenlace>
```

Si `dry_run: true`, antepón `[SIMULACIÓN]` a cada paso de mutación y no lo ejecutes.

**Al terminar**, muestra:

Para `format: human` (predeterminado):
```
══════════════════════════════════════════════
RESUMEN DEL RESULTADO
  <Métrica>:        <valor>
  Errores:          0
  Archivo:          <nombre del archivo o "ninguno">
══════════════════════════════════════════════
```

Para `format: json`, muestra:
```json
{
  "skill": "<slug-de-la-skill>",
  "store": "<dominio>",
  "started_at": "<ISO8601>",
  "completed_at": "<ISO8601>",
  "dry_run": false,
  "steps": [
    {
      "step": 1,
      "operation": "<OperationName>",
      "type": "query",
      "params_summary": "<texto>",
      "result_summary": "<texto>",
      "skipped": false
    }
  ],
  "outcome": {
    "metric_key": 0,
    "errors": 0,
    "output_file": null
  }
}
```

## Formato de salida
`human`: cantidad de productos categorizados, un CSV (`product, old_category, new_category, confidence`) y una lista «por revisar» con los que quedaron bajo el umbral. `json`: `{ categorized, needs_review, errors, output_file }`.

## Manejo de errores
| Error | Causa | Solución |
|-------|-------|----------|
| `THROTTLED` | Límite de solicitudes de la API | Espera 2 s y reintenta hasta 3 veces |
| Sin coincidencia en la taxonomía | Producto de nicho o ambiguo | Agrégalo a la lista por revisar; no adivines |
| `userErrors` al actualizar | ID de categoría inválido | Regístralo, omítelo y continúa |

## Buenas prácticas
- Elige el nodo más específico (hoja) del que estés seguro: los agentes emparejan con más precisión las categorías profundas que las de primer nivel.
- Deja `only_missing: true` en la primera pasada; recategorizar asignaciones existentes es más riesgoso y conviene revisarlo.
- Alinear la categoría con las colecciones de tu tienda multiplica el beneficio: así los agentes y los filtros del sitio coinciden.
- Vuelve a ejecutar `shopify-auditoria-agentes-ia` para confirmar que mejoró el pilar Coincidencia.
